前缀和 (Prefix Sum) 是一种常用的数组预处理技巧,用于高效计算数组中某个区间的和。
假设有一个长度为 n 的数组 nums,可以通过以下方式计算前缀和数组 prefixSum:
vector<int> prefixSum(n);
prefixSum[0] = nums[0];
for (int i = 1; i < n; i++) {
prefixSum[i] = prefixSum[i-1] + nums[i];
}
计算完成后,prefixSum[i] 表示数组 nums 的前 i+1 个元素的和。例如,prefixSum[0] 就等于 nums[0],prefixSum[1] 就等于 nums[0] + nums[1],以此类推。
使用前缀和数组可以高效计算某个区间的和。假设要计算 nums 的第 i 个元素到第 j 个元素的和,可以通过以下方式计算:
int sum = prefixSum[j];
if (i > 0) {
sum -= prefixSum[i-1];
}
这样,sum 就等于 nums[i] + nums[i+1] + ... + nums[j]。
二维前缀和 (2D Prefix Sum) 是前缀和的拓展形式,用于高效计算二维数组中某个矩形区域的和。假设有一个 m 行 n 列的二维数组 grid,可以通过以下方式计算二维前缀和数组 prefixSum:
vector<vector<int>> prefixSum(m, vector<int>(n));
prefixSum[0][0] = grid[0][0];
for (int i = 1; i < m; i++) {
prefixSum[i][0] = prefixSum[i-1][0] + grid[i][0];
}
for (int j = 1; j < n; j++) {
prefixSum[0][j] = prefixSum[0][j-1] + grid[0][j];
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
prefixSum[i][j] = prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1] + grid[i][j];
}
}
计算完成后,prefixSum[i][j] 表示二维数组 grid 中以 (0,0) 为左上角,以 (i,j) 为右下角的矩形区域的和。例如,prefixSum[0][0] 就等于 grid[0][0],prefixSum[1][1] 就等于 grid[0][0] + grid[1][0] + grid[0][1] + grid[1][1]。
使用二维前缀和数组可以高效计算任意矩形区域的和。假设要计算二维数组 grid 中以 (i1,j1) 为左上角,以 (i2,j2) 为右下角的矩形区域的和,可以通过以下方式计算:
int sum = prefixSum[i2][j2];
if (i1 > 0) {
sum -= prefixSum[i1-1][j2];
}
if (j1 > 0) {
sum -= prefixSum[i2][j1-1];
}
if (i1 > 0 && j1 > 0) {
sum += prefixSum[i1-1][j1-1];
}
这样,sum 就等于 grid[i1][j1] + grid[i1+1][j1] + ... + grid[i2][j2]。