Count subarrays that contain exactly k odd numbers.
Start with the concrete trace below. It shows the state the algorithm must carry as it runs.
Problem trace
Count Number of Nice Subarrays: Count endings with at most 3 odds and at most 2 odds at every R, then subtract 14 - 12.
Input and goalCount subarrays that contain exactly `k` odd numbers.
Read the first odd at R = 0Both windows start at 0. Each has one valid ending at R, so totals become at_most(3) = 1 and at_most(2) = 1.
L<=3L<=2R1011221314
ranges<=3 [0..0]; <=2 [0..0]additions1 and 1totals1 and 1
Read the second odd at R = 1Both budgets still fit. Each left boundary stays 0, adding R - L + 1 = 2 endings; totals become 3 and 3.
L<=3L<=210R11221314
ranges<=3 [0..1]; <=2 [0..1]additions2 and 2totals3 and 3
Read the even value at R = 2The even value spends no odd budget. Both L pointers stay 0 and each window adds 2 - 0 + 1 = 3 endings; totals become 6 and 6.
L<=3L<=21011R221314
ranges<=3 [0..2]; <=2 [0..2]additions3 and 3totals6 and 6
Third odd forces only L<=2 rightAt R = 3 the <=3 window still starts at 0 and adds 4. The <=2 budget goes negative, so remove nums[0] = 1 and move L<=2 to 1, adding 3.
L<=310L<=21122R1314
ranges<=3 [0..3]; <=2 [1..3]directionL<=3 stays 0; L<=2: 0 -> 1additions4 and 3totals10 and 9
Fourth odd advances both boundariesAt R = 4, remove nums[0] = 1 for <=3 and nums[1] = 1 for <=2. The windows add 4 and 3 endings, producing 14 - 12 = 2 exact matches.
10L<=311L<=22213R14
ranges<=3 [1..4]; <=2 [2..4]directionL<=3: 0 -> 1; L<=2: 1 -> 2additions4 and 3totals14 and 12result14 - 12 = 2
Recognize it
Use it when subarrays must contain exactly k nonnegative events, while an at-most-k window can be repaired monotonically by moving its left boundary right.
Keep true
For each R, every start from L through R satisfies the relevant at-most limit, so that pass adds exactly R - L + 1 valid endings. The running total includes all right endpoints processed so far.
Reuse it
Convert exact monotone counts into at_most(k) - at_most(k - 1); at each right endpoint, the difference between the two valid-start ranges counts exactly-k subarrays ending there.
Read it this way: Both windows start at 0. Each has one valid ending at R, so totals become at_most(3) = 1 and at_most(2) = 1. Step through the frames to watch the state change. The last frame shows the answer or the stopping condition.
Pattern: Exact count from two sliding windows.
Simple idea: Counting exactly k can be hard. Count subarrays with at most k, then
remove subarrays with at most k - 1.
exactly(k) = at_most(k) - at_most(k - 1)
def number_of_nice_subarrays(nums: list[int], odd_count: int) -> int: def at_most(limit: int) -> int: if limit < 0: return 0 left = 0 total = 0 for right, num in enumerate(nums): limit -= num % 2 while limit < 0: limit += nums[left] % 2 left += 1 total += right - left + 1 return total return at_most(odd_count) - at_most(odd_count - 1)