LeetCode-前缀和
🧠 通过提前累计数组的“历史和”,将任意连续区间的求和问题,转化为两次前缀值的相减。
一句话结论:
👉pre 数组要比原数组的长度多一
pre[0] = 0 是为了统一公式,避免边界特判
前缀和 + 哈希: 找历史区间
⭐ 模板
前缀和
初始化
int n = nums.length;// 前缀和数组,多开一位
int[] pre = new int[n + 1];
pre[0] = 0;// [可选] 记录结果
int res = 0;循环处理(构建 / 使用前缀和)
构建前缀和
for (int i = 0; i < n; i++) {
pre[i + 1] = pre[i] + nums[i];
}使用前缀和(查询区间)
// 区间 [l, r] 的和
int sum = pre[r + 1] - pre[l];
二维前缀和
初始化
int m = matrix.length;
int n = matrix[ 0].length;// 二维前缀和数组,多开一行一列(多开一行一列是“哨兵设计”,用空间换逻辑统一,避免所有边界特判)
int[][] pre = new int[m + 1][n + 1];// 第 0 行、第 0 列默认都是 0
循环处理(构建前缀和)
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
pre[i + 1][j + 1] =
pre[i][j + 1] // 上 + pre[i + 1][j] // 左 - pre[i][j] // 左上 + matrix[i][j]; // 自己
}
}使用前缀和(查询区间)
查询矩形 [r1, c1] ~ [r2, c2](闭区间)
int sum = pre[r2 + 1][c2 + 1] - pre[r1][c2 + 1] - pre[r2 + 1][c1] + pre[r1][c1];
前缀和 + 哈希
初始化
int n = nums.length;// 记录「前缀和(总距离) <-> 出现次数」
Map<Integer, Integer> map = new HashMap<>();// 多开一位:表示“什么都不选”的前缀和
map.put(0, 1);int target = 0; // 当前前缀和/余数
int res = 0; // res 代表数组中「和等于 k 的子数组(连续区间)」的个数循环处理(构建 / 使用前缀和)
for (int i = 0; i < n; i++) {// 构建前缀和
target += nums[i];// target - pre = k ,所以 target - k = pre ,pre 代表的是之前某个位置的前缀和
if (map.containsKey(target - k)) {
res += map.get(target - k);
}// 更新当前前缀和出现次数
map.put(target, map.getOrDefault(target, 0) + 1);
}返回结果
return res;
Notice
- 哈希表存的是「次数」,不是下标(大多数题)
Map<Integer, Integer> map;
含义通常是:
key = 前缀和 (从起点(数组下标 0)出发,走到当前位置时,累计的总距离)
value = 这个前缀和出现过多少次
- 顺序非常重要(先算答案,再更新 map)
✅ 正确顺序
1 | sum += nums[i]; |
- 区间元素
区间内不能重复用同一个位置的元素,不同区间之间可以重叠,所以元素位置可以被“重复使用”
- 二维前缀和
初始化多开一行一列
构建:上 + 左 − 左上 + 自己
查询:大 − 上 − 左 + 左上
- 什么场景用什么方法
一维前缀和:频繁地计算数组中任意一段连续子数组的和
二维前缀和:频繁地计算矩阵中任意矩形区域的和
前缀和+哈希:不关心具体的区间位置,只关心“ 有多少个”或“ 是否存在”满足条件的区间
相关练习题
1. LeetCode 303. 区域和检索 - 数组不可变
题意: 给定一个整数数组 nums,处理以下类型的多个查询:
计算索引 left 和 right (包含 left 和 right)之间的 nums 元素的 和 ,其中 left <= right
实现 NumArray 类:
NumArray(int[] nums) 使用数组 nums 初始化对象
int sumRange(int left, int right) 返回数组 nums 中索引 left 和 right 之间的元素的 总和 ,包含 left 和 right 两点(也就是 nums[left] + nums[left + 1] + … + nums[right] )
2. LeetCode 560. 和为 K 的子数组
题意: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。
3. LeetCode 304. 二维区域和检索 - 矩阵不可变
题意: 给定一个二维矩阵 matrix,以下类型的多个请求:
计算其子矩形范围内元素的总和,该子矩阵的 左上角 为 (row1, col1) ,右下角 为 (row2, col2) 。
实现 NumMatrix 类:
NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初始化
int sumRegion(int row1, int col1, int row2, int col2) 返回 左上角 (row1, col1) 、右下角 (row2, col2) 所描述的子矩阵的元素 总和

