前缀和
一维前缀和
前缀和技巧适⽤于快速、频繁地计算⼀个索引区间内的元素之和。
示例:
输入:
["NumArray", "sumRange", "sumRange", "sumRange"]
[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]
输出:
[null, 1, -1, -3]
解释:
NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]);
numArray.sumRange(0, 2); // return 1 ((-2) + 0 + 3)
numArray.sumRange(2, 5); // return -1 (3 + (-5) + 2 + (-1))
numArray.sumRange(0, 5); // return -3 ((-2) + 0 + 3 + (-5) + 2 + (-1))
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/range-sum-query-immutable
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
暴力解法(容易超出时间限制):
class NumArray {
private int[] nums;
public NumArray(int[] nums) {
this.nums = nums;
}
public int sumRange(int left, int right) {
int res = 0;
for(int i = left; i <= right; i++){
res += nums[i];
}
return res;
}
}
*使用前缀和解法:
class NumArray {
private int[] preNums;
public NumArray(int[] nums) {
int length = nums.length;
// 第一个位置默认是 0
preNums = new int[length + 1];
// 构造前缀和
for(int i = 1; i < preNums.length; i++){
preNums[i] = preNums[i - 1] + nums[i - 1];
}
}
public int sumRange(int left, int right) {
return preNums[right + 1] - preNums[left];
}
}
通过图表示的两个一维数组,可以看到当需要求nums中[2,4]元素和时,可以转换为求preSum[4+1] - preSum[2]
即 nums[right - left] = preSum[right + 1] - preSum[left]
这样,sumRange 函数仅仅需要做⼀次减法运算,避免了每次进⾏ for 循环调⽤,最坏时间复杂度为常数O(1)。
二维前缀和
示例 1:
输入:
["NumMatrix","sumRegion","sumRegion","sumRegion"]
[[[[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]]],[2,1,4,3],[1,1,2,2],[1,2,2,4]]
输出:
[null, 8, 11, 12]
解释:
NumMatrix numMatrix = new NumMatrix([[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]]]);
numMatrix.sumRegion(2, 1, 4, 3); // return 8 (红色矩形框的元素总和)
numMatrix.sumRegion(1, 1, 2, 2); // return 11 (绿色矩形框的元素总和)
numMatrix.sumRegion(1, 2, 2, 4); // return 12 (蓝色矩形框的元素总和)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/range-sum-query-2d-immutable
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
首先需要根据传入的二维数组构造二维的前缀和,然后再输出给定范围内所有元素的和。
构造二维数组的前缀和
当需要构造第[i,j]项的前缀和时,即获取当前项左边一格的前缀和加上,然后加上当前项上边一个的前缀和,加完之后还有一个重合的部分,需要减掉,最后再加上当前指定的项的值就可以求出当前项的前缀和。
preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1] + nums[i - 1][j - 1] - preSum[i - 1][j - 1];
class NumMatrix {
private int[][] preSum;
public NumMatrix(int[][] nums) {
int row = nums.length,col = nums[0].length;
preSum = new int[row + 1][col + 1];
for(int i = 1; i < row; i++){
for(int j = 1; j < col;j++){
preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1] + nums[i-1][j-1] - preSump[i - 1][j - 1];
}
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
return preSum[row2 + 1][col2 + 1] - preSum[row1][col2+1] - preSum[row2+1][col1] + preSum[row1][col1];
}
}