2Brute2Best
🔥0

Binary Subarrays With Sum

Medium·LeetCode #930Basic Anchor
LeetCode
30-Second Mental ModelExactly K = atMost(goal) − atMost(goal − 1)
Complexity:O(N²)→O(N)
Key Insight

Counting subarrays with sum ≤ k is easy with a sliding window. So count sum ≤ goal, count sum ≤ goal − 1, and subtract. What is left is exactly the subarrays with sum goal.

Core Validity Invariant

In each pass, the window is valid when sum ≤ k. Adding elements can only make the sum bigger and removing them can only make it smaller, so this rule is safe to shrink on — unlike "sum = goal".

01

Problem

You are given an array nums that contains only 0s and 1s, and a number goal.

Count how many contiguous, non-empty subarrays add up to exactly goal.

Input

A binary array nums (every value is 0 or 1) and an integer goal.

Output

The number of non-empty subarrays whose sum equals goal.

Example 1
Input: nums = [1, 0, 1, 0, 1], goal = 2
Output: 4

The subarrays with sum 2 are [1,0,1] (indices 0..2), [1,0,1,0] (0..3), [0,1,0,1] (1..4) and [1,0,1] (2..4).

Example 2
Input: nums = [0, 0, 0, 0, 0], goal = 0
Output: 15

Every subarray is all zeros, so every one of the 5·6/2 = 15 subarrays has sum 0.

Constraints
  • • 1 ≤ nums.length ≤ 3 · 10^4
  • • nums[i] is either 0 or 1
  • • 0 ≤ goal ≤ nums.length
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    If I fix where a subarray ends, how many different starts could give the same sum?

  2. 2.

    What does a 0 do to the sum when it enters or leaves the window?

  3. 3.

    If my window has sum exactly goal, should I shrink it or not? Can I tell?

  4. 4.

    Is "sum ≤ goal" easier to keep true with a window than "sum = goal"? Why?

  5. 5.

    If I can count subarrays with sum ≤ x for any x, how do I get the ones with sum = x?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceFix each start, grow the end, count when the sum hits goalO(N²)O(1)
BetterCount earlier prefix sums equal to (current prefix − goal)O(N)O(N)
OptimalTwo at-most windows; their difference is the exactly-goal countO(N)O(1)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “contiguous subarrays”We are counting ranges [l..r] → window or prefix sum.
  • “count how many”The answer is a count, so each right end adds a number of starts (right − left + 1), not a max.
  • “sum equals exactly goal”"Exactly" breaks the shrink rule → split into two "at most" counts.
  • “only 0s and 1s”No negatives, so "sum ≤ k" behaves well for a window. With negatives, only the prefix-sum version works.
Contiguous range+count+sum exactly goal+non-negative values→Exactly K = atMost(goal) − atMost(goal − 1)

This is the anchor of the Exactly K sub-pattern. You already know how to count "at most" subarrays (the At Most K sub-pattern). Here the rule is "sum ≤ k" on a 0/1 array, and the new move is the subtraction. The same problem is also a classic Prefix Sum + hash map problem (Subarray Sum Equals K). Know both: prefix sums work even with negative numbers; the two-window trick only works when values are non-negative, but uses O(1) space.

10

Don't make this mistake

Counting with a single "sum == goal" window
✗ while (sum > goal) sum -= nums[left++]; if (sum == goal) count++;
✓ return atMost(goal) - atMost(goal - 1);

For one right end, several starts can give sum goal (they differ only by zeros on the left). This code counts just one of them. On [0,0,1], goal 1, it returns 1 instead of 3.

Forgetting atMost(−1)
✗ int atMost(vector<int>& nums, int k) { int left = 0, sum = 0, count = 0; ...
✓ if (k < 0) return 0;

When goal = 0 you call atMost(−1). Without the guard, while (sum > -1) is always true (a sum is never negative), so left runs past right and then off the end of the array. No subarray has a negative sum, so the answer is 0.

Adding 1 per step instead of right − left + 1
✗ count += 1;
✓ count += right - left + 1;

We count subarrays, not windows. All starts from left to right give a valid subarray ending at right.

Using the window trick when there are negative numbers

This is a pattern-confusion trap. On a general integer array (like Subarray Sum Equals K), "sum ≤ k" is no longer monotonic — adding a negative number makes the sum smaller. There you must use the prefix sum + hash map approach. The two-window trick works here only because values are 0 or 1.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Sliding Window translate into production architectures and low-level memory mechanics.