📜  用 K(偶数,奇数)对最小化子数组的长度

📅  最后修改于: 2022-05-13 01:57:09.825000             🧑  作者: Mango

用 K(偶数,奇数)对最小化子数组的长度

给定一个由N个正整数组成的数组arr[]和一个整数K ,任务是找到子数组的最小长度,使得至少存在 K对偶数和奇数元素,前提是偶数元素出现奇数元素之前。如果不存在任何这样的子数组,则打印“-1”

例子:

朴素方法:解决给定问题的最简单方法是生成给定数组的所有可能子数组,并在每个子数组中找到满足给定标准的对数。检查所有子数组后,打印具有至少 K对偶数和奇数元素的子数组的最小长度,以使偶数元素出现在奇数元素之前。

时间复杂度: O(N 4 )
辅助空间: O(1)

有效的方法:给定的问题可以通过使用两指针技术来解决。然后考虑一个大小为N的数组A[]

  • 考虑两个指针p1p2,将 p1 初始化为0并将 p2 初始化为-1 ,这两个指针将表示当前窗口大小。
  • 假设有两个变量num_pairs (存储有效对的数量)和final_ans (存储具有至少K个有效对的最小可能子数组的长度,并使用INT_MAX进行初始化)。
  • 按照以下步骤操作,直到p2超出范围,即直到p2
  • p1固定在同一位置并不断增加p2并在增加 p2 的同时继续添加新生成的有效对。继续这个过程,直到有效对的数量小于K。一旦num_pairs变为至少K ,更新final_ans并停止。
  • 现在,开始增加 p1并将p2 固定在同一位置(在上述步骤之后)。在增加 p1 的同时,继续减去作为包含元素A[p1]的结果的有效对,然后增加 p1。这个过程一直持续到有效对的数量大于或等于K为止。在执行此过程时,随着 p1 和 p2 的变化,跟踪最小长度子数组 (fin_ans)。
  • 返回final_ans

计算 {p1, p2} 范围内的有效对数:

  • 为直到索引 i, A[0, i] 的偶数和奇数元素的数量维护一个累积计数数组 evens[N] 和 odd[N]
  • 现在,每当指针 p2 增加时,我们将通过包含元素A[p2]生成的有效对的数量添加到num_pairs。有两种情况:

    情况1:A[p2]偶数时,通过将该元素考虑到现有子数组 (A[p1, p2-1]) 中,有效对数不会增加。

    情况 2:A[p2]奇数时,通过将该元素考虑到现有的子数组 (A[p1, p2-1]) 中,将生成与数组内偶数个数相等的有效对数范围 {p1, p2-1}。由于该范围内的每个偶数都与这个新添加的奇数元素形成一个新对,因此可以使用数组evens[N]直接计算。

  • 现在,在增加指针 p1 的同时,从包含元素A[p1]生成的num_pairs中减去有效的数量。

    有两种情况:

    情况 1:A[p1]奇数时,通过从现有子数组 (A[p1, p2]) 中删除该元素,有效对的数量不会减少。

    情况 2:A[p1]偶数时,通过从现有子数组 (A[p1, p2]) 中删除该元素,应删除等于范围内奇数个数的有效对数 { p1+1, p2}。由于范围 A{p+1, p2} 中的每个奇数都会与偶数 A[p1] 形成一对,因此可以使用数组odds[N]直接计算。

下面是上述方法的实现:

C++
#include 
using namespace std;
  
// Function to calculate the length of the
// smallest possible sub array with at least K
// valid pairs.
int CalculateMinimumSubarray(int A[], int N, int K)
{
    // Vector to store the cumulative count of the number
    // of even numbers and odd numbers.
    // For every i, evens[i] and odds[i] represents
    // the number of evens and odd elements
    // encountered till index 'i'
    vector evens(N, 0), odds(N, 0);
  
    if (A[0] % 2 == 0)
        evens[0] = 1;
    else
        odds[0] = 1;
  
    // Calculating the cumulative even and
    // odd vectors
    for (int i = 1; i < N; i++) {
        evens[i] += evens[i - 1] + (A[i] % 2 == 0);
        odds[i] += odds[i - 1] + (A[i] % 2 == 1);
    }
  
    // Store the minimum length subarray with
    // atleast K valid pairs
    int final_ans = INT_MAX;
  
    // Initializing two pointers.
    int p1 = 0, p2 = -1;
  
    // Stores the number of valid pairs in
    // the range {p1, p2}
    int num_pairs = 0;
  
    // Incrementing p2
    while (p2 < N) {
  
        // Incrementing pointer p2 until there
        // are atleast K valid pairs
        // between the range {p1, p2}.
        while (p2 < N && num_pairs < K) {
            p2++;
  
            // If p2 >= N, stop.
            if (p2 >= N) {
                break;
            }
  
            // If A[p2] is an even number, then
            // the number of valid pairs won't
            // increase, so just continue.
            if (A[p2] % 2 == 0) {
                continue;
            }
  
            // If A[p2] is an odd number, then those many
            // number of valid pairs will be generated which
            // which are equal to the number of even numbers
            // within the range {p1, p2-1}. Since every even
            // number forms a new pair with this odd element.
            int no_evens;
            if (p1 == 0) {
                no_evens = evens[p2];
            }
            else {
                no_evens = evens[p2] - evens[p1 - 1];
            }
  
            // Increment the num_pairs variable with
            // the number of even numbers in the range
            // {p1, p2-1} as calculated above.
            num_pairs = num_pairs + no_evens;
  
            // Update final_ans
            if (num_pairs >= K) {
                final_ans = min(final_ans, p2 - p1 + 1);
            }
        }
        if (p2 >= N) {
            break;
        }
  
        // Increment the pointer p1 until
        // num_pairs >= K.
        while (num_pairs >= K && p1 < p2) {
  
            // Update final_ans
            if (num_pairs >= K) {
                final_ans = min(final_ans, p2 - p1 + 1);
            }
  
            // If A[p1] is an odd number, then removing that
            // element won't decrease the num_pairs.
            if (A[p1] % 2 != 0) {
                p1++;
                continue;
            }
  
            // If A[p1] is an even number, then we should
            // subtract those number of valid pairs from
            // num_pairs which is equal to the number of odd
            // numbers in the range {p1+1, p2}. Since every
            // odd number in the range {p1+1, p2} would have
            // formed a pair with the even number at A[p1]
            int no_odds;
            if (p1 == 0) {
                no_odds = odds[p2];
            }
            else {
                no_odds = odds[p2] - odds[p1 - 1];
            }
            // now we decrease the num_pairs with the value
            // calculated above, that is number of odd
            // numbers from A[p1+1, p2]
            num_pairs = num_pairs - no_odds;
            p1++;
        }
    }
  
    // If final_ans is updated atleast once,
    // then it means there is atleast one sub-array
    // of some size with atleast K valid pairs.
    // And however we have calculated the subarray
    // of minimum length.
    // So we return its length.
    if (final_ans != INT_MAX) {
        return final_ans;
    }
  
    // If the final_ans is never updated,
    // it means that there is no subarray
    // of any size with atleast K valid
    // pairs. So we return -1.
    return -1;
}
  
// Driver Code
int main()
{
    int N = 5;
    int K = 2;
    int A[5] = { 1, 2, 3, 4, 5 };
  
    cout << CalculateMinimumSubarray(A, N, K) << endl;
}


Java
import java.util.Arrays;
  
class GFG {
  
    // Function to calculate the length of the
    // smallest possible sub array with at least K
    // valid pairs.
    public static int CalculateMinimumSubarray(int A[], int N, int K) 
    {
        
        // Vector to store the cumulative count of the number
        // of even numbers and odd numbers.
        // For every i, evens[i] and odds[i] represents
        // the number of evens and odd elements
        // encountered till index 'i'
        int[] evens = new int[N];
        int[] odds = new int[N];
        Arrays.fill(evens, 0);
        Arrays.fill(odds, 0);
  
        if (A[0] % 2 == 0)
            evens[0] = 1;
        else
            odds[0] = 1;
  
        // Calculating the cumulative even and
        // odd vectors
        for (int i = 1; i < N; i++) {
            evens[i] += evens[i - 1] + ((A[i] % 2 == 0) ? 1 : 0);
            odds[i] += odds[i - 1] + ((A[i] % 2 == 1) ? 1 : 0);
        }
  
        // Store the minimum length subarray with
        // atleast K valid pairs
        int final_ans = Integer.MAX_VALUE;
  
        // Initializing two pointers.
        int p1 = 0, p2 = -1;
  
        // Stores the number of valid pairs in
        // the range {p1, p2}
        int num_pairs = 0;
  
        // Incrementing p2
        while (p2 < N) {
  
            // Incrementing pointer p2 until there
            // are atleast K valid pairs
            // between the range {p1, p2}.
            while (p2 < N && num_pairs < K) {
                p2++;
  
                // If p2 >= N, stop.
                if (p2 >= N) {
                    break;
                }
  
                // If A[p2] is an even number, then
                // the number of valid pairs won't
                // increase, so just continue.
                if (A[p2] % 2 == 0) {
                    continue;
                }
  
                // If A[p2] is an odd number, then those many
                // number of valid pairs will be generated which
                // which are equal to the number of even numbers
                // within the range {p1, p2-1}. Since every even
                // number forms a new pair with this odd element.
                int no_evens;
                if (p1 == 0) {
                    no_evens = evens[p2];
                } else {
                    no_evens = evens[p2] - evens[p1 - 1];
                }
  
                // Increment the num_pairs variable with
                // the number of even numbers in the range
                // {p1, p2-1} as calculated above.
                num_pairs = num_pairs + no_evens;
  
                // Update final_ans
                if (num_pairs >= K) {
                    final_ans = Math.min(final_ans, p2 - p1 + 1);
                }
            }
            if (p2 >= N) {
                break;
            }
  
            // Increment the pointer p1 until
            // num_pairs >= K.
            while (num_pairs >= K && p1 < p2) {
  
                // Update final_ans
                if (num_pairs >= K) {
                    final_ans = Integer.min(final_ans, p2 - p1 + 1);
                }
  
                // If A[p1] is an odd number, then removing that
                // element won't decrease the num_pairs.
                if (A[p1] % 2 != 0) {
                    p1++;
                    continue;
                }
  
                // If A[p1] is an even number, then we should
                // subtract those number of valid pairs from
                // num_pairs which is equal to the number of odd
                // numbers in the range {p1+1, p2}. Since every
                // odd number in the range {p1+1, p2} would have
                // formed a pair with the even number at A[p1]
                int no_odds;
                if (p1 == 0) {
                    no_odds = odds[p2];
                } else {
                    no_odds = odds[p2] - odds[p1 - 1];
                }
                
                // now we decrease the num_pairs with the value
                // calculated above, that is number of odd
                // numbers from A[p1+1, p2]
                num_pairs = num_pairs - no_odds;
                p1++;
            }
        }
  
        // If final_ans is updated atleast once,
        // then it means there is atleast one sub-array
        // of some size with atleast K valid pairs.
        // And however we have calculated the subarray
        // of minimum length.
        // So we return its length.
        if (final_ans != Integer.MAX_VALUE) {
            return final_ans;
        }
  
        // If the final_ans is never updated,
        // it means that there is no subarray
        // of any size with atleast K valid
        // pairs. So we return -1.
        return -1;
    }
  
    // Driver Code
    public static void main(String args[]) {
        int N = 5;
        int K = 2;
        int A[] = { 1, 2, 3, 4, 5 };
  
        System.out.println(CalculateMinimumSubarray(A, N, K));
    }
}
  
// This code is contributed by saurabh_jaiswal.


Python3
import sys
  
# Function to calculate the length of the
# smallest possible sub array with at least K
# valid pairs.
def CalculateMinimumSubarray(A, N, K):
    
    # Vector to store the cumulative count of the number
    # of even numbers and odd numbers.
    # For every i, evens[i] and odds[i] represents
    # the number of evens and odd elements
    # encountered till index 'i'
    evens = [0 for i in range(N)]
    odds = [0 for i in range(N)]
  
    if (A[0] % 2 == 0):
        evens[0] = 1
    else:
        odds[0] = 1
  
    # Calculating the cumulative even and
    # odd vectors
    for i in range(1,N,1):
        evens[i] += evens[i - 1] + (A[i] % 2 == 0)
        odds[i] += odds[i - 1] + (A[i] % 2 == 1)
  
    # Store the minimum length subarray with
    # atleast K valid pairs
    final_ans = sys.maxsize
  
    # Initializing two pointers.
    p1 = 0
    p2 = -1
  
    # Stores the number of valid pairs in
    # the range {p1, p2}
    num_pairs = 0
  
    # Incrementing p2
    while (p2 < N):
  
        # Incrementing pointer p2 until there
        # are atleast K valid pairs
        # between the range {p1, p2}.
        while (p2 < N and num_pairs < K):
            p2 += 1
  
            # If p2 >= N, stop.
            if (p2 >= N):
                break
  
            # If A[p2] is an even number, then
            # the number of valid pairs won't
            # increase, so just continue.
            if (A[p2] % 2 == 0):
                continue
  
            # If A[p2] is an odd number, then those many
            # number of valid pairs will be generated which
            # which are equal to the number of even numbers
            # within the range {p1, p2-1}. Since every even
            # number forms a new pair with this odd element.
            no_evens = 0
            if (p1 == 0):
                no_evens = evens[p2]
            else:
                no_evens = evens[p2] - evens[p1 - 1]
  
            # Increment the num_pairs variable with
            # the number of even numbers in the range
            # {p1, p2-1} as calculated above.
            num_pairs = num_pairs + no_evens
  
            # Update final_ans
            if (num_pairs >= K):
                final_ans = min(final_ans, p2 - p1 + 1)
        if (p2 >= N):
            break
  
        # Increment the pointer p1 until
        # num_pairs >= K.
        while (num_pairs >= K and p1 < p2):
  
            # Update final_ans
            if (num_pairs >= K):
                final_ans = min(final_ans, p2 - p1 + 1)
  
            # If A[p1] is an odd number, then removing that
            # element won't decrease the num_pairs.
            if (A[p1] % 2 != 0):
                p1 += 1
                continue
  
            # If A[p1] is an even number, then we should
            # subtract those number of valid pairs from
            # num_pairs which is equal to the number of odd
            # numbers in the range {p1+1, p2}. Since every
            # odd number in the range {p1+1, p2} would have
            # formed a pair with the even number at A[p1]
            no_odds = 0
            if (p1 == 0):
                no_odds = odds[p2]
            else:
                no_odds = odds[p2] - odds[p1 - 1]
            # now we decrease the num_pairs with the value
            # calculated above, that is number of odd
            # numbers from A[p1+1, p2]
            num_pairs = num_pairs - no_odds
            p1 += 1
  
    # If final_ans is updated atleast once,
    # then it means there is atleast one sub-array
    # of some size with atleast K valid pairs.
    # And however we have calculated the subarray
    # of minimum length.
    # So we return its length.
    if (final_ans != sys.maxsize):
        return final_ans
  
    # If the final_ans is never updated,
    # it means that there is no subarray
    # of any size with atleast K valid
    # pairs. So we return -1.
    return -1
  
# Driver Code
if __name__ == '__main__':
    N = 5
    K = 2
    A = [1, 2, 3, 4, 5]
  
    print(CalculateMinimumSubarray(A, N, K))
      
    # This code is contributed by SURENDRA_GANGWAR.


C#
using System;
  
public class GFG{
          
      // Function to calculate the length of the
    // smallest possible sub array with at least K
    // valid pairs.
    public static int CalculateMinimumSubarray(int[] A, int N, int K) 
    {
        
        // Vector to store the cumulative count of the number
        // of even numbers and odd numbers.
        // For every i, evens[i] and odds[i] represents
        // the number of evens and odd elements
        // encountered till index 'i'
        int[] evens = new int[N];
        int[] odds = new int[N];
        Array.Fill(evens, 0);
        Array.Fill(odds, 0);
  
        if (A[0] % 2 == 0)
            evens[0] = 1;
        else
            odds[0] = 1;
  
        // Calculating the cumulative even and
        // odd vectors
        for (int i = 1; i < N; i++) {
            evens[i] += evens[i - 1] + ((A[i] % 2 == 0) ? 1 : 0);
            odds[i] += odds[i - 1] + ((A[i] % 2 == 1) ? 1 : 0);
        }
  
        // Store the minimum length subarray with
        // atleast K valid pairs
        int final_ans = Int32.MaxValue;
  
        // Initializing two pointers.
        int p1 = 0, p2 = -1;
  
        // Stores the number of valid pairs in
        // the range {p1, p2}
        int num_pairs = 0;
  
        // Incrementing p2
        while (p2 < N) {
  
            // Incrementing pointer p2 until there
            // are atleast K valid pairs
            // between the range {p1, p2}.
            while (p2 < N && num_pairs < K) {
                p2++;
  
                // If p2 >= N, stop.
                if (p2 >= N) {
                    break;
                }
  
                // If A[p2] is an even number, then
                // the number of valid pairs won't
                // increase, so just continue.
                if (A[p2] % 2 == 0) {
                    continue;
                }
  
                // If A[p2] is an odd number, then those many
                // number of valid pairs will be generated which
                // which are equal to the number of even numbers
                // within the range {p1, p2-1}. Since every even
                // number forms a new pair with this odd element.
                int no_evens;
                if (p1 == 0) {
                    no_evens = evens[p2];
                } else {
                    no_evens = evens[p2] - evens[p1 - 1];
                }
  
                // Increment the num_pairs variable with
                // the number of even numbers in the range
                // {p1, p2-1} as calculated above.
                num_pairs = num_pairs + no_evens;
  
                // Update final_ans
                if (num_pairs >= K) {
                    final_ans = Math.Min(final_ans, p2 - p1 + 1);
                }
            }
            if (p2 >= N) {
                break;
            }
  
            // Increment the pointer p1 until
            // num_pairs >= K.
            while (num_pairs >= K && p1 < p2) {
  
                // Update final_ans
                if (num_pairs >= K) {
                    final_ans = Math.Min(final_ans, p2 - p1 + 1);
                }
  
                // If A[p1] is an odd number, then removing that
                // element won't decrease the num_pairs.
                if (A[p1] % 2 != 0) {
                    p1++;
                    continue;
                }
  
                // If A[p1] is an even number, then we should
                // subtract those number of valid pairs from
                // num_pairs which is equal to the number of odd
                // numbers in the range {p1+1, p2}. Since every
                // odd number in the range {p1+1, p2} would have
                // formed a pair with the even number at A[p1]
                int no_odds;
                if (p1 == 0) {
                    no_odds = odds[p2];
                } else {
                    no_odds = odds[p2] - odds[p1 - 1];
                }
                
                // now we decrease the num_pairs with the value
                // calculated above, that is number of odd
                // numbers from A[p1+1, p2]
                num_pairs = num_pairs - no_odds;
                p1++;
            }
        }
  
        // If final_ans is updated atleast once,
        // then it means there is atleast one sub-array
        // of some size with atleast K valid pairs.
        // And however we have calculated the subarray
        // of minimum length.
        // So we return its length.
        if (final_ans != Int32.MaxValue) {
            return final_ans;
        }
  
        // If the final_ans is never updated,
        // it means that there is no subarray
        // of any size with atleast K valid
        // pairs. So we return -1.
        return -1;
    }
  
    // Driver Code
    static public void Main (){
  
        int N = 5;
        int K = 2;
        int[] A = { 1, 2, 3, 4, 5 };
  
        Console.WriteLine(CalculateMinimumSubarray(A, N, K));
    }
}
  
// This code is contributed by Dharanendra L V.


Javascript


输出
4

时间复杂度:O(N)
辅助空间:O(N)