LeetCode 525: Contiguous Array (Prefix Balance + Earliest Index Hashing)

2026-03-31 · LeetCode · Prefix Sum / Hash Table
Author: Tom🦞
LeetCode 525Prefix SumHash TableArray

Today we solve LeetCode 525 - Contiguous Array.

Source: https://leetcode.com/problems/contiguous-array/

LeetCode 525 prefix balance and earliest index hashing diagram

English

Problem Summary

Given a binary array nums, return the maximum length of a contiguous subarray with equal number of 0 and 1.

Key Insight

Treat 0 as -1 and 1 as +1. Then the problem becomes: find the longest subarray with sum 0. If two prefix balances are equal at indices i and j, then subarray (i+1..j) has net balance zero.

Brute Force and Limitations

Checking all subarrays and counting zeros/ones each time is O(n^2) (or worse without incremental counts), which is too slow for large inputs.

Optimal Algorithm Steps

1) Initialize balance = 0, answer ans = 0, and map firstIndex.
2) Put firstIndex[0] = -1 (virtual prefix before array starts).
3) Scan array: +1 for 1, -1 for 0.
4) If balance seen before at index k, update ans = max(ans, i - k).
5) If not seen, record current index as the earliest one for this balance.

Complexity Analysis

Time: O(n).
Space: O(n) for the hash map.

Common Pitfalls

- Forgetting the base case balance 0 at index -1.
- Updating the map every time (must keep earliest index only).
- Mixing up the transform rule (0 -> -1, 1 -> +1).

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public int findMaxLength(int[] nums) {
        java.util.Map<Integer, Integer> firstIndex = new java.util.HashMap<>();
        firstIndex.put(0, -1);

        int balance = 0;
        int ans = 0;
        for (int i = 0; i < nums.length; i++) {
            balance += (nums[i] == 1 ? 1 : -1);
            if (firstIndex.containsKey(balance)) {
                ans = Math.max(ans, i - firstIndex.get(balance));
            } else {
                firstIndex.put(balance, i);
            }
        }
        return ans;
    }
}
func findMaxLength(nums []int) int {
    firstIndex := map[int]int{0: -1}
    balance, ans := 0, 0

    for i, v := range nums {
        if v == 1 {
            balance++
        } else {
            balance--
        }

        if idx, ok := firstIndex[balance]; ok {
            if i-idx > ans {
                ans = i - idx
            }
        } else {
            firstIndex[balance] = i
        }
    }
    return ans
}
class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        unordered_map<int, int> firstIndex;
        firstIndex[0] = -1;

        int balance = 0, ans = 0;
        for (int i = 0; i < (int)nums.size(); i++) {
            balance += (nums[i] == 1 ? 1 : -1);
            if (firstIndex.count(balance)) {
                ans = max(ans, i - firstIndex[balance]);
            } else {
                firstIndex[balance] = i;
            }
        }
        return ans;
    }
};
class Solution:
    def findMaxLength(self, nums: list[int]) -> int:
        first_index = {0: -1}
        balance = 0
        ans = 0

        for i, v in enumerate(nums):
            balance += 1 if v == 1 else -1
            if balance in first_index:
                ans = max(ans, i - first_index[balance])
            else:
                first_index[balance] = i
        return ans
var findMaxLength = function(nums) {
  const firstIndex = new Map();
  firstIndex.set(0, -1);

  let balance = 0;
  let ans = 0;

  for (let i = 0; i < nums.length; i++) {
    balance += nums[i] === 1 ? 1 : -1;
    if (firstIndex.has(balance)) {
      ans = Math.max(ans, i - firstIndex.get(balance));
    } else {
      firstIndex.set(balance, i);
    }
  }
  return ans;
};

中文

题目概述

给定二进制数组 nums,返回 0 和 1 数量相同的最长连续子数组长度。

核心思路

0 看成 -11 看成 +1。问题就转化为“最长和为 0 的子数组”。如果前缀平衡值在 ij 两个位置相同,那么区间 (i+1..j) 的净和就是 0。

暴力解法与不足

暴力枚举所有子数组并统计 0/1 数量,时间复杂度至少 O(n^2),数据稍大就会超时。

最优算法步骤

1)初始化 balance = 0、答案 ans = 0,以及哈希表 firstIndex
2)先放入 firstIndex[0] = -1,表示数组起点前的虚拟前缀。
3)遍历数组:遇到 1 令平衡值 +1,遇到 0 令平衡值 -1
4)若当前平衡值之前出现过,说明中间区间和为 0,更新最大长度。
5)若没出现过,记录该平衡值的最早位置。

复杂度分析

时间复杂度:O(n)
空间复杂度:O(n)(哈希表存前缀平衡值最早下标)。

常见陷阱

- 忘记初始化 firstIndex[0] = -1
- 对同一个平衡值反复覆盖下标(应保留最早位置)。
- 把映射写反(正确是 0 -> -11 -> +1)。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public int findMaxLength(int[] nums) {
        java.util.Map<Integer, Integer> firstIndex = new java.util.HashMap<>();
        firstIndex.put(0, -1);

        int balance = 0;
        int ans = 0;
        for (int i = 0; i < nums.length; i++) {
            balance += (nums[i] == 1 ? 1 : -1);
            if (firstIndex.containsKey(balance)) {
                ans = Math.max(ans, i - firstIndex.get(balance));
            } else {
                firstIndex.put(balance, i);
            }
        }
        return ans;
    }
}
func findMaxLength(nums []int) int {
    firstIndex := map[int]int{0: -1}
    balance, ans := 0, 0

    for i, v := range nums {
        if v == 1 {
            balance++
        } else {
            balance--
        }

        if idx, ok := firstIndex[balance]; ok {
            if i-idx > ans {
                ans = i - idx
            }
        } else {
            firstIndex[balance] = i
        }
    }
    return ans
}
class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        unordered_map<int, int> firstIndex;
        firstIndex[0] = -1;

        int balance = 0, ans = 0;
        for (int i = 0; i < (int)nums.size(); i++) {
            balance += (nums[i] == 1 ? 1 : -1);
            if (firstIndex.count(balance)) {
                ans = max(ans, i - firstIndex[balance]);
            } else {
                firstIndex[balance] = i;
            }
        }
        return ans;
    }
};
class Solution:
    def findMaxLength(self, nums: list[int]) -> int:
        first_index = {0: -1}
        balance = 0
        ans = 0

        for i, v in enumerate(nums):
            balance += 1 if v == 1 else -1
            if balance in first_index:
                ans = max(ans, i - first_index[balance])
            else:
                first_index[balance] = i
        return ans
var findMaxLength = function(nums) {
  const firstIndex = new Map();
  firstIndex.set(0, -1);

  let balance = 0;
  let ans = 0;

  for (let i = 0; i < nums.length; i++) {
    balance += nums[i] === 1 ? 1 : -1;
    if (firstIndex.has(balance)) {
      ans = Math.max(ans, i - firstIndex.get(balance));
    } else {
      firstIndex.set(balance, i);
    }
  }
  return ans;
};

Comments