# 数组前缀和

关键

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

  • 题目中有连续,就应该条件反射想到滑动窗口和前缀和

  • 先写出暴力解,然后找暴力解的瓶颈, 根据瓶颈就很容易知道应该用什么数据结构和算法去优化

  • 前缀和算法模板

class PrefixSum {
    // 前缀和数组
    private int[] prefix;

    /* 输入一个数组,构造前缀和 */
    public PrefixSum(int[] nums) {
        prefix = new int[nums.length + 1];
        // 计算 nums 的累加和
        for (int i = 1; i < prefix.length; i++) {
            prefix[i] = prefix[i - 1] + nums[i - 1];
        }
    }

    /* 查询闭区间 [i, j] 的累加和 */
    public int query(int i, int j) {
        return prefix[j + 1] - prefix[i];
    }
}

# 303. 区域和检索 - 数组不可变 (opens new window)

// 方式一:暴力解法 直接获取left和right的元素求和

/**
 * @param {number[]} nums
 */
// var NumArray = function(nums) {
//     this.nums = nums
// };

// /**
//  * @param {number} left
//  * @param {number} right
//  * @return {number}
//  */
// NumArray.prototype.sumRange = function(left, right) {
//     let sum = 0
//     for (let i = left; i <= right; i++){
//         sum += this.nums[i]
//     }
//     return sum
// };

// 方式二: 暴力的问题是每次执行 sumRange 方法的时候都会遍历一次 所以直接在初始化的时候求出所有的结果,sumRange 的时候直接去取值就行
// nums    = [-2, 0, 3, -5, 2, -1]
// resu= [0, -2, -2, 1,-4, -2, -3]

var NumArray = function (nums) {
  this.nums = nums
  this.result = new Array(this.nums.length + 1).fill(0) // 第一个项要为0 preSum 要多一项
  for (let i = 1; i < this.result.length; i++) {
    this.result[i] = this.nums[i - 1] + this.result[i - 1] // preSum[i] = preSum[i-1] + nums[i-1]
  }
  console.log(this.result)
}

NumArray.prototype.sumRange = function (left, right) {
  return this.result[right + 1] - this.result[left]
}

# 304. 二维区域和检索 - 矩阵不可变 (opens new window)

/**
 * @param {number[][]} matrix
 */
var NumMatrix = function (matrix) {
  // 构造一个前缀和的二位矩阵
  const m = matrix.length
  const n = matrix[0].length
  const res = new Array(m + 1).fill(0).map((item) => new Array(n + 1).fill(0))
  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      // 计算每个矩阵 [0, 0, i, j] 的元素和
      res[i][j] = res[i - 1][j] + res[i][j - 1] + matrix[i - 1][j - 1] - res[i - 1][j - 1]
    }
  }
  this.preSum = res
}

/**
 * @param {number} row1
 * @param {number} col1
 * @param {number} row2
 * @param {number} col2
 * @return {number}
 */
NumMatrix.prototype.sumRegion = function (row1, col1, row2, col2) {
  const preSum = this.preSum
  return preSum[row2 + 1][col2 + 1] - preSum[row1][col2 + 1] - preSum[row2 + 1][col1] + preSum[row1][col1]
}

/**
 * Your NumMatrix object will be instantiated and called as such:
 * var obj = new NumMatrix(matrix)
 * var param_1 = obj.sumRegion(row1,col1,row2,col2)
 */