Browse curriculum

Count Number of Nice Subarrays

Count the contiguous subarrays that contain exactly k odd numbers, as subarrays with at most k odds minus those with at most k - 1, each a sliding window.

Problem Understanding

Count Number of Nice Subarrays: a contiguous subarray is nice if it contains exactly k odd numbers. Given nums and k, return the number of nice subarrays.

Examples: [1,1,2,1,1], k 3 → 2; [2,4,6], k 1 → 0; [2,2,2,1,2,2,1,2,2,2], k 2 → 16.

The Intuition: Only Parity Matters

Odd numbers count, even numbers are filler. That makes this Binary Subarrays With Sum in disguise:

  1. atMost(g): a sliding window that shrinks while it holds more than g odds and adds right − left + 1 each step.
  2. Exactly k = atMost(k) − atMost(k − 1).

The prefix-count alternative is the same idea as Subarray Sum Equals K.

Interactive Walkthrough

k = 3 · BOLD = ODD · atMost(3) − atMost(2)

EXACTLY = AT MOST − AT MOST

pass 1: at most 3 odd

1

0

1

1

2

2

1

3

1

4

odds

:

count

:

answer

:

 

Exactly 3 odd numbers = (at most 3) − (at most 2)

Next

atMost(3): count subarrays with at most 3 odd numbers

Free preview: the first 9 of 29 steps

nums

k

Odd numbers are bold. Two passes run, at most k and at most k − 1; on each count step the shaded cells are the starting points counted. Try Example 3 to see evens multiply the count.

Dry Run Table

Input: [1,1,2,1,1], k = 3.

Pass Counts per right Total
atMost(3) 1, 2, 3, 4, 4 14
atMost(2) 1, 2, 3, 3, 3 12

Answer: 14 − 12 = 2 ([1,1,2,1] and [1,2,1,1]).

The Solution Template

The Binary Subarrays With Sum helper, counting odd numbers.

Count Number of Nice Subarrays Code
1var numberOfSubarrays = function(nums, k) {
2 const atMost = (g) => {
3 if (g < 0) return 0;
4 let left = 0, odds = 0, count = 0;
5 for (let right = 0; right < nums.length; right++) {
6 odds += nums[right] & 1;
7 while (odds > g) odds -= nums[left++] & 1;
8 count += right - left + 1;
9 }
10 return count;
11 };
12 return atMost(k) - atMost(k - 1);
13};

Edge Cases & Common Mistakes

  • No odd numbers: both passes count everything; the answer is 0.
  • k larger than the number of odds: the answer is 0.
  • Counting only when odds == k: misses windows that differ by evens at the ends.
  • Forgetting the g < 0 guard: only matters if k could be 0; LeetCode has k ≥ 1, but the helper stays correct with it.
  • Long runs of evens: they are why the count can be large; use the subtraction, not enumeration.

Summary

Treat odd as 1 and even as 0, count windows with at most k odds with a shrinking window, and return atMost(k) − atMost(k − 1). O(n) time, O(1) space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Write atMost(g)

    Slide a window: add nums[right] % 2, shrink while the window has more than g odds, add right - left + 1.

  2. Handle g < 0

    atMost of a negative number returns 0.

  3. Subtract

    Return atMost(k) - atMost(k - 1).

Frequently asked questions

How is this the same as Binary Subarrays With Sum?

Replace every number by nums[i] % 2: odd numbers become 1 and even numbers 0. The number of odd values in a subarray is then its sum, so 'exactly k odd numbers' is 'sum exactly k' on a binary array, and the same atMost(k) - atMost(k - 1) solution applies.


Why can't one window count 'exactly k' directly?

Even numbers do not change the count of odds, so a window with exactly k odds can still grow or shrink through evens and stay valid. There is no single left boundary per right end. With 'at most k', once a window has too many odds, every bigger window does too, so a shrinking window works.


Is there another O(n) approach?

Yes. Prefix counts: keep how many prefixes had each number of odds so far; at each index add the count of prefixes with (odds so far - k). Or count, for each block of k odds, the evens before its first and after its last odd and multiply. All are linear.


Why use nums[i] & 1?

It is the lowest bit, 1 for odd and 0 for even, which is exactly nums[i] % 2 for non-negative numbers, the problem's input.

New to the technique behind this problem? Watch it run step by step:

Sliding Window Visualization

Applying for software engineering roles? Free, no sign-up:

AI resume checker: match your resume to the job description