308. Range Sum Query 2D - Mutable
第三次出现需要缓存的题目了
题干:
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).
The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.
The matrix is only modifiable by the update function.
You may assume the number of calls to update and sumRegion function is distributed evenly.
You may assume that row1 ≤ row2 and col1 ≤ col2.
解释:
类似之前的题
思考:
这个题和之前的题相比就多了一个update函数,所以只需要思考这个函数怎么用就可以了。更新所有被这个update函数影响的缓存值,因为我们缓存的是以右下角定义的矩形值,所以所有包含这个数的缓存值都需要被更新。 那么这时候就要思考如何改进了,实际上可以用缓存存储当前这一行到目前为止的所有点的和,然后再求的时候只要计算这一列的所有点的和集合即可。这样搞有一个好处就是update的时候非常简单,因为只需要更新本行的值即可。但是求和的时候相对就会麻烦一些。
答案:
class NumMatrix {
private int[][] matrix;
private int[][] rowSumArr; // 保存每个元素(i, j)在第i行的前j+1项的和。
private int rowCount;
private int colCount;
public NumMatrix(int[][] matrix) {
this.matrix = matrix;
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return;
}
rowCount = matrix.length;
colCount = matrix[0].length;
rowSumArr = new int[rowCount][colCount];
for (int i = 0; i < rowCount; i++) {
rowSumArr[i][0] = matrix[i][0];
for (int j = 1; j < colCount; j++) {
rowSumArr[i][j] = rowSumArr[i][j-1] + matrix[i][j];
}
}
}
public void update(int row, int col, int val) {
matrix[row][col] = val;
int fromCol = col;
if (col == 0) {
rowSumArr[row][col] = matrix[row][col];
fromCol = col + 1;
}
for (int j = fromCol; j < colCount; j++) {
rowSumArr[row][j] = rowSumArr[row][j-1] + matrix[row][j];
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
int sum = 0;
for (int i = row1; i <= row2; i++) {
sum += col1 == 0 ? rowSumArr[i][col2] : rowSumArr[i][col2] - rowSumArr[i][col1-1];
}
return sum;
}
}
/**
* Your NumMatrix object will be instantiated and called as such:
* NumMatrix obj = new NumMatrix(matrix);
* obj.update(row,col,val);
* int param_2 = obj.sumRegion(row1,col1,row2,col2);
*/