2Brute2Best
🔥0

Contiguous Array

Medium·LeetCode #525Basic Anchor
LeetCode
30-Second Mental ModelPrefix Sum (balance) + first-index hash map
Complexity:O(N²)→O(N)
Key Insight

Keep a running balance from index 0. If the balance at index i equals the balance at an earlier index j, then everything in nums[j+1..i] added up to 0, so it is balanced. Store the first index where each balance appeared (with balance 0 at index −1). At each i, the longest balanced subarray ending at i has length i − first[balance].

Core Validity Invariant

nums[j+1..i] has equal 0s and 1s exactly when the running balance at j equals the running balance at i.

01

Problem

You are given an array nums that holds only 0s and 1s.

Find the longest contiguous subarray that has the same number of 0s and 1s, and return its length. If there is no such subarray, return 0.

Input

A binary array nums (every value is 0 or 1).

Output

The length of the longest subarray with equally many 0s and 1s.

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

The whole array has one 0 and one 1.

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

[0, 1] or [1, 0] both work. The whole array has two 0s and one 1, so it does not.

Example 3
Input: nums = [0, 1, 1, 1, 1, 1, 0, 0, 0]
Output: 6

[1, 1, 1, 0, 0, 0] (indices 3..8) has three of each. No longer subarray is balanced.

Constraints
  • • 1 ≤ nums.length ≤ 10^5
  • • nums[i] is either 0 or 1
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.

    What single number could tell me "this part has as many 0s as 1s"?

  2. 2.

    If I count a 1 as +1 and a 0 as −1, what is the sum of a balanced subarray?

  3. 3.

    If the running total is the same at two different indices, what happened in between?

  4. 4.

    I want the longest answer. For a fixed end, which earlier index should I pair it with?

  5. 5.

    How do I handle a balanced subarray that starts right at index 0?

03

Brute force 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 with a running balance, check balance == 0O(N²)O(1)
OptimalSame balance seen before ⇒ the part in between is balanced; store the first index of each balanceO(N)O(N)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “contiguous subarray”A range [l..r] → think window or prefix sums.
  • “same number of 0s and 1s”Two counts that must cancel → map 0 → −1, 1 → +1 and look for sum 0.
  • “longest”Pair each end with the **earliest** matching prefix → store the first index, not a count.
Contiguous range+two kinds of values must balance+longest→Prefix Sum (balance) + first-index hash map

This is the anchor of the Prefix state / balance sub-pattern. The new move compared with Exact sum + hash map is the transform: turn the array into +1/−1 so that "balanced" becomes "sum 0", which becomes "same prefix value seen before". And because we want the longest subarray (not a count), the map stores the first index of each balance instead of how many times it appeared. The next questions keep this idea but change the state: a bitmask of parities (vowels in even counts), or a balance that must be greater than 0 (well-performing interval).

10

Don't make this mistake

Trying a sliding window

This is a pattern-confusion trap. A window needs a rule like "if it is broken, shrinking can fix it". Here there is none: a window with too many 1s might become balanced by adding more 0s on the right, not by removing from the left. And removing a 0 from the left makes it worse. So you cannot tell when to shrink. "Equal counts" is an exact-sum condition (sum = 0 after the ±1 transform), which is a prefix-sum job.

Overwriting the stored index
✗ first[balance] = i; // every time
✓ if (!first.count(balance)) first[balance] = i;

If you update the map every time, it keeps the last index of each balance. Then i − first[balance] pairs the end with the closest start instead of the farthest, and you get shorter answers. On [0, 1, 0, 1] it returns 2 instead of 4.

Forgetting the −1 seed
✗ unordered_map<int, int> first; // empty
✓ first[0] = -1;

Without it, a balanced subarray that starts at index 0 is never found. On [0, 1] the balance goes −1, 0 and 0 was never stored, so the answer comes out 0 instead of 2.

Seeding with 0 instead of −1
✗ first[0] = 0;
✓ first[0] = -1;

Length is i − first[balance]. The empty prefix ends before index 0, i.e. at −1. Seeding 0 makes every subarray that starts at index 0 one too short.

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 Prefix Sum translate into production architectures and low-level memory mechanics.