算法——前缀和

29 阅读2分钟

前缀和主要适用的场景是原始数组不会被修改的情况下,频繁查询某个区间的累加和

1.算法——一维数据前缀和 力扣303 「区域和检索 - 数组不可变」

image.png 实现思路:根据输入的数组 计算出前缀数组,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 「区域和检索 - 数组不可变」

image.png 实现思路: 结合一维数组的前缀和思路 用一个二维数组存储每一行一维数组的前缀和 则要求[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 的子数组」

image.png 实现思路: 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
};