前缀和数组:
前缀和技巧适用于快速、频繁地计算一个索引区间内的元素之和。(仅仅适用于原数组不变的情况,如果原数组经常修改,则需要考虑差分数组。)

看两道例题就清楚了:
1. 303. 区域和检索 - 数组不可变 - 力扣(LeetCode)

由于要频繁计算某个区间内的元素之和,暴力解法复杂度太大,显然前缀和比较合适,代码如下:
class NumArray { //前缀和数组 int[] sumArr; public NumArray(int[] nums) { sumArr = new int[nums.length + 1]; for(int i = 1; i < sumArr.length; i++){ sumArr[i] = sumArr[i - 1] + nums[i - 1]; } } public int sumRange(int left, int right) { //计算[i, j]范围内的和是用sumArr[j + 1] - sumArr[i]计算 return sumArr[right + 1] - sumArr[left]; } } /** * Your NumArray object will be instantiated and called as such: * NumArray obj = new NumArray(nums); * int param_1 = obj.sumRange(left,right); */
2. 304. 二维区域和检索 - 矩阵不可变 - 力扣(LeetCode)
这道题将前缀和数组扩展到了二维:

在构建前缀和数组时,可以定义前缀和数组(i, j)的值为原矩阵到由(0, 0)到(i - 1, j - 1)构成的子矩阵内部的元素之和,任意矩阵都可以由几个子矩阵的加减运算得到,原理如下图:

代码如下:
class NumMatrix { int[][] sumArr; public NumMatrix(int[][] matrix) { int m = matrix.length, n = matrix[0].length; sumArr = new int[m + 1][n + 1]; //初始化前缀和数组 for(int i = 1; i < m + 1; i++){ for(int j = 1; j < n + 1; j++){ sumArr[i][j] = sumArr[i][j - 1] + sumArr[i - 1][j] + matrix[i - 1][j - 1] - sumArr[i - 1][j - 1]; } } } public int sumRegion(int row1, int col1, int row2, int col2) { // System.out.println("------"); // for(int[] row : sumArr){ // System.out.println(Arrays.toString(row)); // } return sumArr[row2 + 1][col2 + 1] - (sumArr[row2 + 1][col1] + sumArr[row1][col2 + 1] - sumArr[row1][col1]); } } /** * Your NumMatrix object will be instantiated and called as such: * NumMatrix obj = new NumMatrix(matrix); * int param_1 = obj.sumRegion(row1,col1,row2,col2); */
class NumArray {
//前缀和数组
int[] sumArr;
public NumArray(int[] nums) {
sumArr = new int[nums.length + 1];
for(int i = 1; i < sumArr.length; i++){
sumArr[i] = sumArr[i - 1] + nums[i - 1];
}
}
public int sumRange(int left, int right) {
//计算[i, j]范围内的和是用sumArr[j + 1] - sumArr[i]计算
return sumArr[right + 1] - sumArr[left];
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* int param_1 = obj.sumRange(left,right);
*/