Count the number of subarrays with exactly k odd numbers.
Medium
📘 Problem Statement
Given an array of integers nums
and an integer k
. Return the number of sub-arrays which has exactly k
odd numbers.
🔍 Example
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
🛠️ Solution
❌ Brute Force Approach (Inefficient)
- Try all possible subarrays and count how many odd numbers are in each.
- If a subarray contains exactly k odd numbers, increment the count.
def numberOfSubarrays(nums, k):
count = 0
n = len(nums)
for i in range(n):
odd_count = 0
for j in range(i, n):
if nums[j] % 2 == 1:
odd_count += 1
if odd_count == k:
count += 1
elif odd_count > k:
break # optimization
return count
The total complexity of this solution is . Not efficient for large arrays.
⚡ Optimized Approach: Prefix Sum
This approach is similar to the Subarray Sum equals K, with the change being instead of counting the sum, we will transform the problem to count the number of odd numbers seen so far.
💡 Key Idea:
-
Transform the problem:
Count how many odds have been seen up to each index using a prefix sum. Let
odd_count_so_far
be the number of odd numbers encountered up to current index. We want to find how many subarrays have:odd_count_right − odd_count_left = k
-
Track frequency of odd counts using a hashmap:
-
Let
count_map[i]
store how many timesi
odd numbers have been seen. -
For each position, check if
odd_count - k
has been seen before — this means there exists a previous subarray whose difference in odd count is exactlyk
.
📘 Why This Works ?
We track:
-
For each index
i
, how many subarrays ending ati
contain exactlyk
odd numbers. -
Whenever
prefix_odds - k
has occurred before, it means we can form a subarray from that earlier index to current index with exactlyk
odds.
def numberOfSubarrays(nums, k):
from collections import defaultdict
count = 0
prefix_odds = 0
freq = defaultdict(int)
freq[0] = 1 # base case: 0 odd numbers seen at the start
for num in nums:
if num % 2 == 1:
prefix_odds += 1
count += freq[prefix_odds - k]
freq[prefix_odds] += 1
return count
⏱️ Time & Space Complexity
Operation | Complexity |
---|---|
Time | |
Space |