力扣labuladong一刷day17天前缀和数组

力扣labuladong一刷day17天前缀和数组

一、303. 区域和检索 - 数组不可变

题目链接:https://leetcode.cn/problems/range-sum-query-immutable/
思路:本题即为让写一个类用于计算指定区间内的数字和,但如果直接采用for循环的方式,当有很多的输入实例时,会有很多的重复计算,非常浪费时间。
既然是计算区间和的值,那么我们可以提前准备一个前缀和数组,如nums=[a, b, c, d] 前缀和数组为preSum = [a, a+b, a+b+c, a+b+c+d],这样以后再计算区间和只需要使用前缀合数组preSum[right]-preSum[left]即可,这样就把时间复杂度降低到了常量级。是一个不错的小技巧。

class NumArray {

    int[] preSum;

    public NumArray(int[] nums) {
        this.preSum = new int[nums.length+1];
        for (int i = 1; i < preSum.length; i++) {
            preSum[i] = preSum[i-1] + nums[i-1];
        }
    }

    public int sumRange(int left, int right) {
        return preSum[right+1] - preSum[left];
    }
}

二、304. 二维区域和检索 - 矩阵不可变

题目链接:https://leetcode.cn/problems/range-sum-query-2d-immutable/
思路:这两道前缀和的题目让我收益匪浅,使用前缀和的数组提前计算数组,把时间复杂度降低到O(1)。要想搞清楚前缀和数组,首先要在使用之前把定义明确,本题求二维区域和,定义前缀和数组为:preSum[i][j]为nums数组从区间[0,0]到[i-1, j-1]。明确定义后写递推公式,和动态规划的dp数组特别像, preSum[i][j] = preSum[i-1][j] + preSum[i][j-1]+matrix[i-1][j-1] - preSum[i-1][j-1];
我感觉本题其实就是动态规划的应用。

class NumMatrix {
    int[][] preSum;
    public NumMatrix(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        this.preSum = new int[m+1][n+1];
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                preSum[i][j] = preSum[i-1][j] + preSum[i][j-1]+matrix[i-1][j-1] - preSum[i-1][j-1];
            }
        }
    }
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return preSum[row2+1][col2+1] + preSum[row1][col1] - preSum[row2+1][col1] - preSum[row1][col2+1];
    }
}

你可能感兴趣的:(力扣算法题,leetcode,算法,职场和发展,前缀和)