用 K(偶数,奇数)对最小化子数组的长度
给定一个由N个正整数组成的数组arr[]和一个整数K ,任务是找到子数组的最小长度,使得至少存在 K对偶数和奇数元素,前提是偶数元素出现在奇数元素之前。如果不存在任何这样的子数组,则打印“-1” 。
例子:
Input: K = 2, A[] = {1, 2, 3, 4, 5}
Output: 4
Explanation:
The subarray {2, 3, 4, 5} is of length 4, which is minimum. It has at least K(= 2) pairs as {2, 3}, {2, 5} and {4, 5}.
Input: K = 3, A[] = {2, 3, 4, 1, 2, 3}
Output: 4
Explanation: The subarray {2, 3, 4, 1} is of length 4, which is minimum. It has at least K(= 3) pairs as {2, 3}, {2, 1} and {4, 1}.
朴素方法:解决给定问题的最简单方法是生成给定数组的所有可能子数组,并在每个子数组中找到满足给定标准的对数。检查所有子数组后,打印具有至少 K对偶数和奇数元素的子数组的最小长度,以使偶数元素出现在奇数元素之前。
时间复杂度: O(N 4 )
辅助空间: O(1)
有效的方法:给定的问题可以通过使用两指针技术来解决。然后考虑一个大小为N的数组A[] ,
- 考虑两个指针p1和p2,将 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)