前缀和主要适用的场景是原始数组不会被修改的情况下,频繁查询某个区间的累加和
1.算法——一维数据前缀和 力扣303 「区域和检索 - 数组不可变」
实现思路:根据输入的数组 计算出前缀数组,eg:
nums = [3,5,2,-2,4,1]
sums = [0,3,8,10,8,12,13](前缀和数组)
这里根据10=3+5+2
可得sums[i]=nums[i-1]+...+nums[0]
如果要求索引区间【1,4】内的元素和就等于求
【0,4】减【0】
即 sums[5] - sums[1]= 12 - 3 =9
验证一下【1,4】内的元素和:5+2+(-2)+4=9
上代码:
/**
* @param {number[]} nums
求出前缀和
*/
var NumArray = function (nums) {
const n = nums.length;
this.sums = new Array(n + 1).fill(0);
for (let i = 0; i < n; i++) {
this.sums[i + 1] = this.sums[i] + nums[i];
}
};
/**
* @param {number} left
* @param {number} right
* @return {number}
*/
NumArray.prototype.sumRange = function (left, right) {
return this.sums[right + 1] - this.sums[left];
};
2.算法——二维数据前缀和 力扣304 「区域和检索 - 数组不可变」
实现思路:
结合一维数组的前缀和思路 用一个二维数组存储每一行一维数组的前缀和 则要求[1,1,2,2] 即等于要求 sums[1,3]-sums[1,1]+sums[2,3]-sums[2,1]
上代码
/**
* @param {number[][]} matrix
*/
var NumMatrix = function (matrix) {
const row_count = matrix.length
if (row_count > 0) {
const col_count = matrix[0].length;
this.preSum = new Array(row_count).fill(0).map(item => new Array(col_count + 1).fill(0))
for (let i = 0; i < row_count; i++) {
for (let j = 0; j < col_count; j++) {
// this.preSum[0][1] = matrix[0][1] + this.preSum[0][0]
this.preSum[i][j + 1] = this.preSum[i][j] + matrix[i][j]
}
}
}
};
/**
* @param {number} row1
* @param {number} col1
* @param {number} row2
* @param {number} col2
* @return {number}
*/
NumMatrix.prototype.sumRegion = function (row1, col1, row2, col2) {
let result = 0
for (let i = row1; i <= row2; i++) {
result += this.preSum[i][col2 + 1] - this.preSum[i][col1]
}
return result
};
3.算法——前缀和 力扣第560题「和为 K 的子数组」
实现思路:
1.计算数组的前缀和
2.穷举全部的子数组 检查和是不是等于k 是的话计数+1
上代码
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var subarraySum = function(nums, k) {
const n=nums.length
let sums=new Array(n+1).fill(0) // 前缀和数组
for(let i=0;i<n;i++){
sums[i+1]=sums[i]+nums[i]
}
let count=0
for(let right=1;right<=n;right++ ){
for(let left =0;left<right;left++){
if(sums[right]-sums[left]==k){
count++
}
}
}
return count
};