前缀和
前缀和是指一个数组的某下标之前的所有数组元素的和(包含其自身)。前缀和分为一维前缀和,以及二维前缀和。
一维前缀和
preSum[i]
表示第 i 个元素之前的所有元素的和
例如,对于数组 nums = [1, 2, 3, 4],其前缀和数组 preSum
为:
preSum = [0, 1, 3, 6, 10]
应用
前缀和是一种重要的预处理,能够降低算法的时间复杂度。前缀和可以应用于以下问题:
- 快速求数组的区间和
- 求子数组的最大/最小值
- 寻找子数组的和为某个值的方案
- 二维数组的区域和
public class PrefixSum {
public static int[] getPrefixSum(int[] nums) {
int[] preSum = new int[nums.length];
preSum[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
preSum[i] = preSum[i - 1] + nums[i];
}
return preSum;
}
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4};
int[] preSum = getPrefixSum(nums);
// 求区间 [1, 3] 的和
int sum13 = preSum[4] - preSum[0];
// 求子数组的最大值
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
max = Math.max(max, preSum[i] - min(preSum[0:i]));
}
// 寻找子数组的和为 6 的方案
for (int i = 0; i < nums.length; i++) {
for (int j = i; j < nums.length; j++) {
if (preSum[j + 1] - preSum[i] == 6) {
System.out.println(i + ", " + j);
}
}
}
// 求区域 (0, 0) 到 (1, 1) 的和
int sum0011 = preSum[2][2] - preSum[0][0] - preSum[2][0] + preSum[0][1];
}
private static int min(int[] preSum) {
int min = preSum[0];
for (int i = 1; i < preSum.length; i++) {
min = Math.min(min, preSum[i]);
}
return min;
}
}