算法技巧:前缀和数组刷题合集
303. 区域和检索 - 数组不可变
题目要求你实现这样一个类:
class NumArray {
public NumArray(int[] nums) {}
/* 查询闭区间 [left, right] 的累加和 */
public int sumRange(int left, int right) {}
}
sumRange
函数需要计算并返回一个索引区间之内的元素和,没学过前缀和的人可能写出如下代码:
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;
}
}
这样,可以达到效果,但是效率很差,因为sumRange
方法会被频繁调用,而它的时间复杂度是O(N)
,其中N
代表nums
数组的长度。
这道题的最优解法是使用前缀和技巧,将sumRange
函数的时间复杂度降为O(1)
,说白了就是不要在sumRange
里面用 for 循环,咋整?
代码实现:
/**
* @param {number[]} nums
*/
var NumArray = function(nums) {
let presum=[];
presum[0]=0;
for(let i=1;i<nums.length+1;i++){
presum[i]=presum[i-1]+nums[i-1];
}
this.preSum=presum;
};
/**
* @param {number} left
* @param {number} right
* @return {number}
*/
NumArray.prototype.sumRange = function(left, right) {
return this.preSum[right+1]-this.preSum[left]
};
/**
* Your NumArray object will be instantiated and called as such:
* var obj = new NumArray(nums)
* var param_1 = obj.sumRange(left,right)
*/
如果我想求索引区间[1, 4]
内的所有元素之和,就可以通过preSum[5] - preSum[1]
得出。
这样,sumRange
函数仅仅需要做一次减法运算,避免了每次进行 for 循环调用,最坏时间复杂度为常数O(1)
。
304. 二维区域和检索 - 矩阵不可变
如果我想计算红色的这个子矩阵的元素之和,可以用绿色矩阵减去蓝色矩阵减去橙色矩阵最后加上粉色矩阵,而绿蓝橙粉这四个矩阵有一个共同的特点,就是左上角就是(0, 0)
原点。
那么我们可以维护一个二维preSum
数组,专门记录以原点为顶点的矩阵的元素之和,就可以用几次加减运算算出任何一个子矩阵的元素和:
/**
* @param {number[][]} matrix
*/
var NumMatrix = function(matrix) {
let m=matrix.length;
if(m>0){
let n=matrix[0].length;
this.Presum=new Array(m+1).fill(0).map(()=>new Array(n+1).fill(0));
for(let i=1;i<m+1;i++){//计算前缀和,注意0,0要空开,方便计算
for(let j=1;j<n+1;j++){
this.Presum[i][j]=this.Presum[i][j-1]+this.Presum[i-1][j]-this.Presum[i-1][j-1]+matrix[i-1][j-1];
}
}
}
};
/**
* @param {number} row1
* @param {number} col1
* @param {number} row2
* @param {number} col2
* @return {number}
*/
NumMatrix.prototype.sumRegion = function(row1, col1, row2, col2) {
return this.Presum[row2+1][col2+1] - this.Presum[row1][col2+1]-this.Presum[row2+1][col1]+this.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)
*/
https://mp.weixin.qq.com/s/EwAH3JDs5WFO6-LFmI3-2Q
阅读剩余
版权声明:
作者:chun
链接:https://chun53.top/1203.html
文章版权归作者所有,未经允许请勿转载。
THE END