
Problem Statement
The task is to find the number of continuous subarrays in a given array of integers (nums
) that contain exactly k
odd numbers. These subarrays are termed as "nice" subarrays. The input to the function will be the array nums
and the integer k
. The output should be an integer representing how many such "nice" subarrays exist.
Examples
Example 1
Input:
nums = [1,1,2,1,1], k = 3
Output:
2
Explanation:
The only sub-arrays with 3 odd numbers are [1,1,2,1] and [1,2,1,1].
Example 2
Input:
nums = [2,4,6], k = 1
Output:
0
Explanation:
There are no odd numbers in the array.
Example 3
Input:
nums = [2,2,2,1,2,2,1,2,2,2], k = 2
Output:
16
Constraints
1 <= nums.length <= 50000
1 <= nums[i] <= 10^5
1 <= k <= nums.length
Approach and Intuition
The problem involves analyzing subarrays for a specific count of odd numbers. Given the constraints and nature of the problem, a brute-force solution could be too slow, especially with large arrays. Here's an approach to solve the problem efficiently:
Transform the Problem:
Simplify the problem by focusing only on the odd numbers innums
. Convertnums
into a binary representation where1
denotes an odd number and0
denotes an even number.Use Prefix Sum and HashMap:
- The idea is to use a prefix sum to count odd numbers up to each index.
- Create a hashmap to store how many times each count of odd numbers has been seen as a prefix sum.
- For each element, calculate the current count of odd numbers using the prefix sum.
- The key insight is that if at some index
i
the prefix sum isp
, and we have previously seenp-k
x
times (using the hashmap), then there arex
subarrays ending ati
which havek
odd numbers.
Iterate Through Nums:
- Initialize the hashmap with
{0: 1}
to handle the case where a subarray with exactlyk
odd numbers starts from the beginning. - As you iterate through
nums
, update the prefix sum based on whether the current number is odd. - For each updated prefix sum, calculate how many times the
(current prefix sum) - k
has occurred, as it will give the count of subarrays ending at this position that are "nice".
- Initialize the hashmap with
Count "Nice" Subarrays:
- For each index, update the count of "nice" subarrays by adding the count found in the previous step.
- Also, update the hashmap to reflect the current prefix sum count.
Using the data from the examples:
- For
nums = [1,1,2,1,1]
andk = 3
, convert to[1,1,0,1,1]
:- The prefix sums would be
[1, 2, 2, 3, 4]
and you determine counts of reaching each prefix sum consideringk
.
- The prefix sums would be
Considering this method is efficient and direct, it caters well to the constraints provided, specifically handling large arrays up to the length of 50,000.
Solutions
- C++
- Java
- Python
class Solution {
public:
int countKSubarrays(vector<int>& nums, int k) {
return atMostK(nums, k) - atMostK(nums, k - 1);
}
private:
int atMostK(vector<int>& nums, int k) {
int count = 0, result = 0, left = 0;
for (int right = 0; right < nums.size(); right++) {
count += nums[right] % 2;
while (count > k) {
count -= nums[left] % 2;
left++;
}
result += right - left + 1;
}
return result;
}
};
To efficiently compute the number of "nice" subarrays with k
odd numbers in C++, the provided solution implements an approach based on the difference between scenarios when there are at most k
odd numbers versus at most k-1
odd numbers.
- Begin by defining the
countKSubarrays
function which relies on reusing the logic meant to calculate the count of subarrays with at mostk
odd numbers by using the helper functionatMostK
. - Implement the
atMostK
function that will keep track ofcount
, the number of odd numbers,result
, the count of valid subarrays, andleft
, a pointer used for indicating the start of a window. - Utilize a sliding window strategy:
- Incrementally expand the window to include more elements (
right
pointer), updating thecount
of odd elements. - If the
count
exceedsk
, adjust theleft
pointer to shrink the window until thecount
is appropriate again. - Update the count of valid subarrays for each position of the
right
pointer, accumulating results using the expressionresult += right - left + 1
to consider all subarrays ending atright
.
- Incrementally expand the window to include more elements (
This solution is effective in determining the number of subarrays that exactly contain k
odd numbers by leveraging direct subtraction between two conditions, ensuring optimal computation and clearer results through the difference of outcomes for k
and k-1
. This method is highly efficient, using a sliding window approach for a time complexity of O(n) where n is the number of elements in the input array, providing a significant advantage for large datasets.
class Solution {
public int countOddSubarrays(int[] arr, int k) {
return countAtMost(arr, k) - countAtMost(arr, k - 1);
}
private int countAtMost(int[] arr, int k) {
int countOdds = 0, result = 0, left = 0;
for (int right = 0; right < arr.length; right++) {
countOdds += arr[right] % 2;
// Adjust the left index so countOdds is at most k
while (countOdds > k) {
countOdds -= arr[left] % 2;
left++;
}
// Add the number of valid subarrays ending at right
result += right - left + 1;
}
return result;
}
}
This Java solution is designed to solve the problem of counting the number of subarrays with exactly k
odd numbers. The code utilizes two major functions: countOddSubarrays
and countAtMost
.
Start by analyzing the
countOddSubarrays
method. It leverages the operation of helper functioncountAtMost
to find subarrays with at mostk
odd numbers and subarrays with at mostk - 1
odd numbers. The difference between these two counts gives the exact number of subarrays with exactlyk
odd numbers.Dive deeper into the
countAtMost
method, which is a sliding window technique used to maintain a dynamic scope of subarray indices[left, right]
. Here,countOdds
keeps track of the number of odd numbers within the current window.- Iterate over the array using
right
as the moving boundary of the window. - Update the count of odd numbers
countOdds
by checking if the current element is odd. - If
countOdds
exceedsk
, adjust theleft
point of the window to reduce thecountOdds
until it is at mostk
. - For each position of
right
, increment theresult
by the number of valid subarrays ending atright
, which is quantified by the gap betweenright
andleft
plus one (i.e.,right - left + 1
).
- Iterate over the array using
This method efficiently uses the sliding window concept, allowing the function to maintain an adaptive list of candidate subarrays while controlling the maximum allowed odd elements, resulting in an optimal calculation of the desired count of nice subarrays.
class Solution:
def countOddSubarrays(self, array: List[int], count: int) -> int:
return self.subarrayCountLessThanEqual(array, count) - self.subarrayCountLessThanEqual(array, count - 1)
def subarrayCountLessThanEqual(self, array: List[int], threshold: int) -> int:
odd_count, result, left = 0, 0, 0
for right in range(len(array)):
odd_count += array[right] % 2
while odd_count > threshold:
odd_count -= array[left] % 2
left += 1
result += right - left + 1
return result
This Python code defines a method to count the number of subarrays with a given number of odd elements in a list of integers. The solution uses the two-pointer technique to efficiently find the desired subarrays.
The
countOddSubarrays
function calculates the difference between:- The number of subarrays with odd counts less than or equal to
count
- The number of subarrays with odd counts less than
count
This difference effectively returns the number of subarrays that have exactly
count
odd numbers.- The number of subarrays with odd counts less than or equal to
The helper method
subarrayCountLessThanEqual
efficiently counts how many subarrays have odd counts less than or equal to a specified thresholdthreshold
. This is accomplished by using two variables,left
andright
, to maintain a sliding window:- Increment
odd_count
when an odd element is encountered as theright
pointer advances. - If
odd_count
exceeds thethreshold
, increment theleft
pointer to reduce theodd_count
. - Add to the result the number of valid subarrays ending at the current
right
pointer.
- Increment
This systematic approach ensures optimal counting of the subarrays within the given constraints, using a combination of mathematical computation and efficient looping structures.
No comments yet.