力扣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];}
}