基本思路
首先,我们会有一个原始数组,例如 int[] arr = {1, 4, 5, 9, 7, 2}
。
然后会要求我们求解某一段数组的累加和是多少,比如让我们求索引 1 ~ 3 的累加和,即求解answer = arr[1] + arr[2] + arr[3]
。
一般情况下,我们的思路为遍历数组需要的索引位置,累加得到结果。但是,如果我们如果需要频繁去得到某一段数组的累加和,那么每次计算的时间复杂度就是 O(n)
。
现在,我们就用累加和的思路去解决这个问题,使得时间复杂度变为 O(1)
。
- 第1步,根据原始数组构建前缀和数组
- 第2步,通过前缀和数组得到累加结果
核心代码
public class PrefixSum {
/**
* 前缀和数组
*/
private int[] ps;
/**
* 构造我们的前缀和数组
*/
public PrefixSum(int[] arr) {
// 这里注意,我们的前缀和数组的长度要比原始数组大 1
ps = new int[arr.length + 1];
for (int i = 1; i < ps.length; i++) {
ps[i] = ps[i - 1] + arr[i + 1];
}
}
/**
* 计算 start 到 end 的索引范围的累加和
*/
public int sum(int start, int end) {
return ps[end + 1] - ps[start];
}
}
实战例题
303. 区域和检索 - 数组不可变
304. 二维区域和检索 - 矩阵不可变
560. 和为 K 的子数组
应用场景
前缀和主要适用的场景是原始数组不会被修改的情况下,频繁查询某个区间的累加和。