前缀和数组
一、区域和检索-数组不可变
- 区域和检索-数组不可变
- preSum[i]:原数组起始下标到i-1下标的所有数之和
class NumArray {
private int preSum[];
public NumArray(int[] nums) {
//构建前缀和数组
preSum=new int [nums.length+1];
// preSum[0] = 0,便于计算累加和
preSum[0]=1;
for(int i=1;i<nums.length+1;i++){
preSum[i]=preSum[i-1]+nums[i-1];
}
}
//查询闭区间 [left, right] 的累加和
/*
*例如球2,4区间内的和 preSum[4+1]:0,1,2,3,4下标的和
* preSum[2]:0,1
* 两个一减则为下边2,3,4之和
*/
public int sumRange(int left, int right) {
return preSum[right+1]-preSum[left];
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* int param_1 = obj.sumRange(left,right);
*/
二、和为K的子数组
class Solution {
public int subarraySum(int[] nums, int k) {
// map:前缀和 -> 该前缀和出现的次数
HashMap<Integer,Integer> preSum=new HashMap<>();
preSum.put(0,1);
int res=0;
int n=nums.length;
int sum_i=0;
for(int i=0;i<n;i++){
sum_i+=nums[i];
//这是我们想找的前缀和nums[0..j]
int sum_j=sum_i-k;
//如果前面存在这个前缀和,则答案直接更新
if(preSum.containsKey(sum_j)){
res+=preSum.get(sum_j);
}
//把前缀和nums[0..i]加入并记录出资按的次数
//如果没出现过则直接设置为1,若出现过则直接个原来的次数加一
//getOrDefault:如果map中含有sum_i则这个函数值取它原本的值,如果没有则取0
preSum.put(sum_i,preSum.getOrDefault(sum_i,0)+1);
}
return res;
}
}