AI summary
type
status
date
slug
summary
category
tags
icon
password
前缀和技巧适用于快速、频繁地计算一个索引区间内的元素之和。
一维数组中的前缀和
303. 区域和检索 - 数组不可变
给定一个整数数组nums,处理以下类型的多个查询:
- 计算索引
left和right(包含left和right)之间的nums元素的 和 ,其中left <= right实现NumArray类:
NumArray(int[] nums)使用数组nums初始化对象
int sumRange(int i, int j)返回数组nums中索引left和right之间的元素的 总和 ,包含left和right两点(也就是nums[left] + nums[left + 1] + ... + nums[right])
这是一道标准的前缀和问题。核心思路是我们 new 一个新的数组
preSum 出来,preSum[i] 记录 nums[0..i-1] 的累加和,如果我想求索引区间 [1, 4] 内的所有元素之和,就可以通过 preSum[5] - preSum[1] 得出。这样,
sumRange 函数仅仅需要做一次减法运算,避免了每次进行 for 循环调用,时间复杂度为 O(1)。二维矩阵中的前缀和
304. 二维区域和检索 - 矩阵不可变
给定一个二维矩阵matrix,以下类型的多个请求:
- 计算其子矩形范围内元素的总和,该子矩阵的 左上角 为
(row1, col1),右下角 为(row2, col2)。实现NumMatrix类:
NumMatrix(int[][] matrix)给定整数矩阵matrix进行初始化
int sumRegion(int row1, int col1, int row2, int col2)返回 所描述的子矩阵的元素 总和 。
和上面同理,
presum[x][y] 表示 左上角为 (0,0),右下角为 (x,y) 的矩阵元素和。转移关系如下图所示:

拓展延伸
本文讲解的前缀和技巧是利用预计算的
preSum 数组快速计算索引区间内的元素和,但实际上它不仅仅局限于求和,也可以用来快速计算区间内的最大值、最小值、乘积等等。而且前缀和数组经常和其他数据结构或算法技巧相结合,我会在 前缀和技巧经典习题 中结合习题讲解。
还有一个重要的问题:使用前缀和技巧的前提是原数组
nums 不会发生变化。如果原数组中的某个元素改变了,那么
preSum 数组中该元素后面的值就会失效,需要重新花费 O(n) 的时间计算,这就和普通的暴力解法没太大区别了。所以在数组元素可变的场景下,我们不能使用前缀和技巧,而是使用 线段树 这种数据结构来处理区间查询和动态更新。