题目 1:一维前缀和
链接:303. 区域和检索 - 数组不可变 - 力扣(LeetCode)
题目分析
实现一个类,输入数组 nums,多次查询区间 [left, right] 的区间和。数组不会修改。 示例: nums = [-2, 0, 3, -5, 2, -1] sumRange(0,2) → 1 sumRange(2,5) → -1 sumRange(0,5) → -3 核心:如果每次查询都遍历区间,单次查询 O (n),查询次数多就超时。前缀和预处理之后,单次查询 O (1)。
算法原理
定义前缀和数组 preSum,下标从 1 开始 (规避边界判断): preSum[0] = 0 preSum[i] = nums[0] + nums[1] + ... + nums[i-1]
区间 [l, r](原数组下标,从 0 开始)的和公式: sum = preSum[r + 1] - preSum[l]
预处理 O (n),每次查询 O (1)。
代码编写
cpp
class NumArray {
public:
vector<int> preSum;
NumArray(vector<int>& nums) {
int n = nums.size();
preSum.resize(n + 1, 0);
for(int i = 1; i <= n; i++) {
preSum[i] = preSum[i - 1] + nums[i - 1];
}
}
int sumRange(int left, int right) {
return preSum[right + 1] - preSum[left];
}
};
总结
一维前缀和核心:偏移 1 位,preSum 0=0 。记住公式:原数组 [l,r] 和 = preSum[r+1] - preSum[l]。适合静态数组区间求和,数组不能修改;如果单点修改,需要用树状数组 / 线段树。
题目 2:二维前缀和
链接:304. 二维区域和检索 - 矩阵不可变 - 力扣(LeetCode)
题目分析
给定二维矩阵,多次查询子矩形 (row1, col1) 到 (row2, col2) 的和,矩阵不变。 示例: matrix = \[3,0,1,4,2, 5,6,3,2,1, 1,2,0,1,5, 4,1,0,1,7, 1,0,3,0,5 ] sumRegion (2,1,4,3) → 8 核心:二维区间求和,暴力每次遍历矩形 O (mn),多次查询太慢。二维前缀和预处理,查询 O (1)。
算法原理
前缀和数组 preSum 下标从 1 开始 ,preSum[i][j] 代表左上角 (1,1) 到 (i,j) 的矩形和。 递推公式: preSum[i][j] = matrix[i-1][j-1] + preSum[i-1][j] + preSum[i][j-1] - preSum[i-1][j-1]
子矩形 (x1,y1) ~ (x2,y2)(原矩阵下标,从 0 开始): 映射到前缀和下标:a=x1+1, b=y1+1, c=x2+1, d=y2+1 查询公式: sum = preSum[c][d] - preSum[a-1][d] - preSum[c][b-1] + preSum[a-1][b-1]
原理:减去上方一块、左边一块,多减了左上角重叠部分,再加回来。
代码编写
cpp
class NumMatrix {
public:
vector<vector<int>> preSum;
NumMatrix(vector<vector<int>>& matrix) {
int m = matrix.size();
if(m == 0) return;
int n = matrix[0].size();
preSum.assign(m + 1, vector<int>(n + 1, 0));
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
preSum[i][j] = matrix[i-1][j-1] + preSum[i-1][j] + preSum[i][j-1] - preSum[i-1][j-1];
}
}
}
int sumRegion(int row1, int col1, int row2, int col2) {
int a = row1 + 1, b = col1 + 1;
int c = row2 + 1, d = col2 + 1;
return preSum[c][d] - preSum[a-1][d] - preSum[c][b-1] + preSum[a-1][b-1];
}
};
总结
二维前缀和重点:容斥原理,先加、再减、再加回重叠部分。同样适合静态矩阵,预处理 O (mn),查询 O (1)。下标偏移 1 是为了不用单独判断 i=0 或 j=0 的边界。
本篇总结
本篇是前缀和两大基础模板,笔试高频:
- 一维前缀和:preSum 0=0,
[l,r]和 =preSum[r+1]-preSum[l] - 二维前缀和:递推用容斥,查询也用容斥,下标全部 + 1 简化边界
前缀和适用场景:数组 / 矩阵不变,多次区间求和。 ⚠️ 注意:如果题目会单点修改,前缀和不再合适,要换树状数组。

