前缀和技巧适用于快速、频繁地计算一个索引区间内的元素之和。
具体实现原理是构建一个新的数组,新数组中的每i项是原数组前i项和。
1.一维数组前缀和
leetcode303
```Java
class NumArray {
public int[] preNum;
public NumArray(int[] nums) {
preNum=new int[nums.length+1];
for(int i=1;i<preNum.length;i++){
preNum[i]=preNum[i-1]+nums[i-1];
}
}
public int sumRange(int left, int right) {
return preNum[right+1]-preNum[left];
}
}
```
2.二维数组前缀和
leetcode304题
给定⼀个⼆维矩阵 matrix,其中的⼀个⼦矩阵⽤其左上⻆坐标 (row1, col1) 和右下⻆坐标
(row2,col2) 来表示。
请你实现 NumMatrix 类:
1、NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进⾏初始化
2、int sumRegion(int row1, int col1, int row2, int col2) 返回左上⻆ (row1, col1)
,右下⻆ (row2, col2) 所描述的⼦矩阵的元素总和。
解题思路:⼀维数组中的前缀和问题是⾮常类似,只要我们把坐标[0,0]到[i,j]的元素和记录下来,就可以算出任意左上角、右下角所描述的子矩阵的元素总和。
```Java
class NumMatrix {
public int[][] preSum;
public NumMatrix(int[][] matrix) {
int m=matrix.length,n=matrix[0].length;
if(m==0||n==0)return;
//构造前缀和矩阵
preSum=new int[m+1][n+1];
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
//计算每个矩阵[0,0,i,j]的元素和
preSum[i][j]=preSum[i-1][j]+preSum[i][j-1]+matrix[i-1][j-1]-preSum[i-1][j-1];
}
}
}
public int sumRegion(int x1, int y1, int x2, int y2) {
return preSum[x2+1][y2+1] - preSum[x1][y2+1] - preSum[x2+1][y1] +
preSum[x1][y1];
}
}
```
3.和为k的子数组
leetcode560题
给你一个整数组nums和一个整数k,请你统计并返回该数组中和为k的连续子数组的个数。
解题思路:我们可以使用前缀和数组技巧来解这道题,这样连续子数组就很容易求出来,这道题就演化成了两数之差问题。而两数之差问题我们可以使用hash表降低时间复杂度。
```Java
class Solution {
public int subarraySum(int[] nums, int k) {
//map存储前缀和,该前缀和出现的次数
HashMap<Integer,Integer> preSum=new HashMap<>();
preSum.put(0,1);
int num_s=0,res=0;
for(int i=0;i<nums.length;i++){
num_s+=nums[i];
if(preSum.containsKey(num_s-k)){
res += preSum.get(num_s-k);
}
if(preSum.containsKey(num_s)){
preSum.put(num_s,preSum.get(num_s)+1);
}else preSum.put(num_s,1);
}
return res;
}
```