Hard题学算法(二维前缀和+二维差分)

leetcode周赛遇到的hard题,题目在最后,当时做的时候毫无头绪,因为本人差分做的也很少,所有完全没往差分上面想,然后就开始坐牢。所以总结一下前缀和以及差分数组的知识点。

一维前缀和

一次区间和

假设现在有个需求,给想知道指定一维数组某个区间的和,怎么求?

例如数组[1,2,3,4,5,4,3,2,3],数组长度为n,我想知道下标2到5区间内数组元素的和,最直观的做法如下

public int demo(int[] nums, int l, int r) {
    int sum = 0;
    for (int i = l; i <= r; i++) {
        sum += nums[i];
    }
    return sum;
}
复制代码

很显然,没有比这更优的解法了,时间复杂度O(n),空间复杂度O(1)

多次求区间和

1、假设我不仅需要求区间[2,5]的和,我还需要求[1,3]、[4,5]...的和,即我会给m个[l,r],但是数组nums是固定的,同样的,依然可以用上述方法解决,你每次都调用demo方法就可以了,但是这样的时间复杂度是O(n*m)了,很容易超时。

2、对于这种情况我们可以用到前缀和的思想,构造一维数组的前缀和

原来的数组 nums [1,2,3,4,5,4,3,2,3]

前缀和数组 sum  [1,3,6,10,15,19,22,24,27]
复制代码

构造代码如下

for (int i = 1; i < nums.length; i++) {
    nums[i] += nums[i - 1];
}
复制代码

3、现在有了前缀和数组,我们该怎么求区间[l,r]的范围和呢?

不难想到,求区间[l,r]的和,就是求(1+2+3+...+r)-(1+2+3+...+l-1)的和

怎么理解,比如我有个数组是[0,1,2,3,4,5,6,7,8,9,10],我要求[2,4]的和,可以先求[0,4]的和,就是0+1+2+3+4,再求[0,1]的和,就是0+1,那么0+1+2+3+4是不是比0+1多了2+3+4,是不是正好就是区间[2,4]的和?

通解就是sum[l,r] = sum[r] - sum[l - 1] (这里l-1会越界,读者可以特判,或者让数组的长度为n+1)

二维前缀和

类似一维前缀和,如果多次求区间内范围和,就可以用到二维前缀和的思想,那么二维数组的区间是什么? 假设红色矩阵左上角的坐标是[i,j],右下角的坐标是[m,n],用这两个坐标是不是可以圈出这个矩阵了

Hard题学算法(二维前缀和+二维差分)_第1张图片

一次区间和

那现在我这个红色矩阵的和是不是很好求了,直接遍历就可以了

public int demo(int[][] matrix, int i, int j, int m, int n) {
    int sum = 0;
    for (int k = i; k <= m; k++) {
        for (int l = j; l <= n; l++) {
            sum += matrix[k][l];
        }
    }
    return sum;
}
复制代码

多次求区间和

如果我想求多次呢?那每一次都像上面的解法就很慢了,有没有一行代码就能求出来的解

你可能感兴趣的:(算法,leetcode,职场和发展)