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

题目说明

给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)。

image.png

上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。

  • 你可以假设矩阵不可变。
  • 会多次调用 sumRegion 方法
  • 你可以假设 row1 ≤ row2 且 col1 ≤ col2。

示例

例1

1
2
3
4
5
6
7
8
9
10
11
12
给定 matrix = [
[3, 0, 1, 4, 2],
[5, 6, 3, 2, 1],
[1, 2, 0, 1, 5],
[4, 1, 0, 1, 7],
[1, 0, 3, 0, 5]
]

sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12

笔者理解

此题是一道数组算法问题,在力扣题库中被定义为中等题。

解法

当笔者阅读完此题后,发现此题和昨天的每日一题有点相通之处,首先题目中提到sumRegion 方法会多次调用,所有我们不能每计算一次就去原数组中运算一次,我们用一个数组来存储各个位置左上角矩阵各元素的累加和,然后在调用sumRegion 方法时直接给出结果即可,此题需要注意sum数组元素的计算以及sumRegion 方法计算取得位置是否正确,让我们来看看具体如何实现的吧。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class NumMatrix {
int[][] sum;
//存储对应位置左上角的矩阵元素之和

int row;
int column;
//矩阵的长及宽

public NumMatrix(int[][] matrix) {
if(matrix.length==0){ return;}
//空矩阵直接返回

row = matrix.length;
column = matrix[0].length;
sum = new int [row+1][column+1];
//存放和的数组要比原数组多出一行一列,方便进行动态规划

for(int i=1;i<=row;i++){
for(int j=1;j<=column;j++){
sum[i][j] = sum[i][j-1]+sum[i-1][j] - sum[i-1][j-1] +matrix[i-1][j-1];
//当前元素左上角矩阵的元素和等于上方和左方元素的和再减去重复计算的元素和再加上本格元素
}
}
}

public int sumRegion(int row1, int col1, int row2, int col2) {
return sum[row2+1][col2+1]+sum[row1][col1] - (sum[row1][col2+1]+sum[row2+1][col1]);
//返回当前r2,c2矩阵的元素和减去上方和左方元素的和再加上多减去的重复元素
}
}

/**
* Your NumMatrix object will be instantiated and called as such:
* NumMatrix obj = new NumMatrix(matrix);
* int param_1 = obj.sumRegion(row1,col1,row2,col2);
*/

时间和空间效率都还行,可见此解法还比较适合此题;

image.png

总结

本题是今天的每日一题,难度是为中等,感兴趣的朋友都可以去尝试一下,此题还有其他更多的解法,朋友们可以自己逐一尝试。