题目描述:
给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)。
上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。
示例:
给定 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的时候都双重循环求和;初始化时时间复杂度为O(1),求和时时间复杂度为O((row2-row1)*(clo2-col1))
代码实现:
/**
* @param {number[][]} matrix
*/
var NumMatrix = function (matrix) {
this.matrix = matrix;
};
/**
* @param {number} row1
* @param {number} col1
* @param {number} row2
* @param {number} col2
* @return {number}
*/
NumMatrix.prototype.sumRegion = function (row1, col1, row2, col2) {
let sum = 0;
for (let i = row1; i <= row2; i++) {
for (let j = col1; j <= col2; j++) {
sum += this.matrix[i][j];
}
}
return sum;
};
运行结果:
参考了昨天看的一维数组的求和,想到了一个优化的思路
思路:
构造函数初始化时求出(i,j)到(0,0)区域间的和,sumRegion时用大的区域减去不需要计算的区域再加上重合的区域即可;初始化时时间复杂度为O(m*n),sumRegion时时间复杂度为O(1);
代码实现:
/**
* @param {number[][]} matrix
*/
var NumMatrix = function (matrix) {
this.accumulateMatrix = [];
if (matrix.length === 0) return; //确定matrix存在
var n = matrix.length;
var m = matrix[0].length;
for (var i = 0; i <= n; i++) { //开辟dp空间为 n✖️m的矩阵
var rows = [];
for (var j = 0; j <= m; j++) {
rows[j] = 0;
}
this.accumulateMatrix.push(rows);
}
for (var i = 1; i <= n; i++) {
for (var j = 1; j <= m; j++) {
this.accumulateMatrix[i][j] = matrix[i - 1][j - 1] + this.accumulateMatrix[i - 1][j]
+ this.accumulateMatrix[i][j - 1] - this.accumulateMatrix[i - 1][j - 1];
}
}
};
/**
* @param {number} row1
* @param {number} col1
* @param {number} row2
* @param {number} col2
* @return {number}
*/
NumMatrix.prototype.sumRegion = function (row1, col1, row2, col2) {
return this.accumulateMatrix[row2 + 1][col2 + 1] - this.accumulateMatrix[row1][col2 + 1]
- this.accumulateMatrix[row2 + 1][col1] + this.accumulateMatrix[row1][col1];
};
运行结果: