前缀和算法实战:连续数组与矩阵区域和
前缀和是处理区间查询问题的利器,从一维数组到二维矩阵,掌握其核心思想能大幅提升解题效率。今天通过两道经典题目,深入剖析前缀和的一维与二维应用。
031 连续数组
问题描述:
给定一个只包含 0 和 1 的数组 nums,找到最长的连续子数组的长度,使得该子数组中 0 和 1 的数量相等。
思路分析
暴力枚举所有子数组的时间复杂度是 O(n²),对于大数据量显然不可行。我们可以换个角度思考:如果将所有的 0 视为 -1,那么问题就转化为寻找和为 0 的最长子数组。
假设 sum[i] 表示从索引 0 到 i 的前缀和。如果存在两个位置 i 和 j(i < j),使得 sum[j] == sum[i],那么区间 (i, j] 内的元素和必然为 0。因此,我们需要记录每个前缀和第一次出现的位置。
具体步骤如下:
- 初始化哈希表,存入
{0: -1},表示前缀和为 0 时,虚拟的下标为 -1。 - 遍历数组,动态计算当前前缀和。
- 若当前前缀和已在哈希表中,说明找到了一个和为 0 的子数组,更新最大长度。
- 若未出现过,则记录该前缀和及其下标。
注意:我们不需要显式构建前缀和数组,只需维护一个变量累加即可,空间上主要消耗在哈希表存储上。
代码实现
C++ 实现
class Solution {
public:
int findMaxLength(vector<int>& nums) {
unordered_map<int, int> hash;
// 初始状态:前缀和为 0,对应下标 -1
hash[0] = -1;
int sum = 0, ret = 0;
for (int i = 0; i < nums.size(); ++i) {
// 0 记为 -1,1 记为 1
sum += (nums[i] == 0 ? -1 : 1);
if (hash.count(sum)) {
// 之前出现过相同前缀和,计算区间长度
ret = max(ret, i - hash[sum]);
} {
hash[sum] = i;
}
}
ret;
}
};


