- LeetCode303 区域和检索 - 数组不可变
1. 解题技巧:**前缀和数组**,这是一道标准的前缀和问题
2. 思路分析
1. 若如下题解,效率很差,因为sumRange方法会被频繁调用,但是他的时间复杂度为O(N),N为nums数组的长度
```
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;
}
}
```
2. 因此,我们采用前缀和的方式,将sumRange函数的时间复杂度降为O(1),即将循环从sumRange中移出
3. 构造一个前缀和数组int[] preSum,长度为nums.length + 1,preSum[0] = 0, preSum[i] 表示 nums[0] 到 nums[i - 1]的累加和
4. 因此若要计算[left, right]的累加和,即返回preSum[right + 1] (nums数组前right个的累加和) - preSum[left] (nums数组前left - 1 个的累加和)
5.![请添加图片描述](https://img-blog.csdnimg.cn/9b24e81093a845d7a9ec0cb6037bd9a1.png)
3. 代码实现
```
class NumArray {
private int[] preSum;
public NumArray(int[] nums) {
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];
}
}
```
- LeetCode304 二维区域和检索 - 矩阵不可变
1. 思路分析
1. 使用前缀和数组的解题技巧
2. 定义二维数组preSum = new int[matrix.length + 1] [matrix[0].length + 1],preSum[i] [j]存放matrix的子矩阵(0, 0, i - 1 , j - 1)的元素总和
因此preSum[i] [j] = preSum[i -1] [j] + preSum[i] [j + 1] + matrix[i - 1] [j - 1] - preSum[i - 1] [j - 1]
图示如下,注意紫色为蓝色 + 红色,
3. 计算灰色矩阵的元素总和即为 preSum[row2+1] [col2+1] (灰蓝红紫) - preSum[row2] [col1 + 1] (蓝紫) - preSum[row1] [col2 + 1] (红紫) + preSum[row1] [col1] (紫)
2. 代码实现
```
class NumMatrix {
private int[][] preSum;
public NumMatrix(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
if (m == 0 || n == 0) return;
preSum = new int[m + 1][n + 1];
for (int i = 1; i < m + 1; i++) {
for (int j = 1; j < n + 1; 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][col2 + 1] - preSum[row2 + 1][col1] + preSum[row1][col1];
}
}
```