给定一个二维矩阵 matrix,以下类型的多个请求:
计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)
掌握一维前缀和和二维前缀和
进而能掌握一维前缀积和二维前缀积
class NumMatrix {
private:
vector<vector<int>> sums; // 一维前缀和
public:
// 行的一维前缀
NumMatrix(vector<vector<int>>& matrix) {
//在初始化的时候搞一些必要操作
int row = matrix.size();
int col = matrix[0].size();
if(row>0 && col>0) {
// resize完之后,可用size重新获取更新后的大小,同时内存被初始化为0
// sums[i][j]的意思是第i行(i从0开始),前j列元素的总和(j从1开始)
sums.resize(row, vector<int>(col + 1, 0));
for(int i = 0; i < row; i++) {
for(int j = 1; j <= col; j++) {
sums[i][j] = sums[i][j - 1] + matrix[i][j - 1];
}
}
}
}
int sumRegion(int row1, int col1, int row2, int col2) {
int sum = 0;
// sums[0][1]是第0行,前1列的和
// sums[0][2]是第0行,前2列的和
// 行固定好之后,计算列值差
for(int i = row1; i <= row2; i++) {
// 前 col2+1 列的和 减去 前 col1 列的和
// 比如 col1 = 2, col2 = 4
// 则需要计算 0+1+2+3+4列的和 减去 0+1列的和
// 所以就是 前col2+1 列的和减去 前 col1 列的和
sum += (sums[i][col2 + 1] - sums[i][col1]);
}
return sum;
}
};
class NumMatrix {
private:
vector<vector<int>> sums; // 一维前缀和
public:
// 列的一维前缀
NumMatrix(vector<vector<int>>& matrix) {
//在初始化的时候搞一些必要操作
int row = matrix.size();
int col = matrix[0].size();
if(row>0 && col>0) {
// resize完之后,可用size重新获取更新后的大小,同时内存被初始化为0
// sums[i][j]的意思是第j列(j从0开始),前i行元素的总和(i从1开始)
sums.resize(row + 1, vector<int>(col, 0));
for(int j = 0; j < col; j++) {
for(int i = 1; i <= row; i++) {
sums[i][j] = sums[i - 1][j] + matrix[i - 1][j];
}
}
}
}
int sumRegion(int row1, int col1, int row2, int col2) {
int sum = 0;
// sums[1][0]是第0列,前1行的和
// sums[3][0]是第0行,前3行的和
// 列固定好之后,计算行值差
for(int j = col1; j <= col2; j++) {
// 前 row2+1 行的和 减去 前 row1 行的和
// 比如 row1 = 2, row2 = 4
// 则需要计算 0+1+2+3+4行的和 减去 0+1行的和
// 所以就是 前row2+1 行的和减去 前 row1 行的和
sum += (sums[row2+1][j] - sums[row1][j]);
}
return sum;
}
};
【二维前缀和】
class NumMatrix {
private:
vector<vector<int>> sums; // 二维前缀和
public:
NumMatrix(vector<vector<int>>& matrix) {
//在初始化的时候搞一些必要操作
int row = matrix.size();
int col = matrix[0].size();
if(row>0 && col>0) {
// resize完之后,可用size重新获取更新后的大小,同时内存被初始化为0
// sums[i][j]的意思是前i行(i从1开始),前j列元素的总和(j从1开始)
sums.resize(row + 1, vector<int>(col + 1, 0));
for(int i = 1; i <= row; i++) {
for(int j = 1; j <= col; j++) {
sums[i][j] = sums[i - 1][j] + sums[i][j - 1] + matrix[i - 1][j - 1] - sums[i - 1][j - 1];
}
}
}
}
int sumRegion(int row1, int col1, int row2, int col2) {
return sums[row2+1][col2+1] + sums[row1][col1] - sums[row2+1][col1] - sums[row1][col2+1];
}
};
eg
对于数组matrix:
4 5 7
2 1 3
9 8 6
计算之后的sums就是
0 0 0 0
0 4 9 16
0 6 12 22
0 15 29 45
前i行前j列的值 = 前i-1行前j-1列的值+第i-1行前j-1列的值+第j-1列前i-1行的值+matrix[i-1][j-1]的值
前3行前3列的值 = 前2行前2列的值+第2行前2列的值+第2列前2行的值+matrix[2][2]的值
第2行指的是从0开始的行,第2列指的是从0开始的列
如何计算 第i-1行前j-1列的值 ?
第i-1行前j-1列的值 = 前i行前j-1列的值 - 前i-1行前j-1列的值
第2行前2列的值 = 前3行前2列的值 - 前2行前2列的值 = 第2行前2列的值
如何计算 第j-1列前i-1行的值 ?
第j-1列前i-1行的值 = 前i-1行前j列的值 - 前i-1行前j-1列的值
第2列前2行的值 = 前2行前3列的值 - 前2行前2列的值 = 前2行第2列的值
sums[i][j] = sums[i - 1][j] + sums[i][j - 1] + matrix[i - 1][j - 1] - sums[i - 1][j - 1];
那么 第row1行第col1列 到 第row2行第col2列之间的和 =
前row2+1行前col2+1列的值 - 前row1行前col1列的值 - (第row1行~第row2行)前col1列的值 - 前row1行(第col1列~第col2列)
进而可以表示为:
(第row1行~第row2行)前col1列的值 = 前row2+1行前col1列的值 - 前row1行前col1列的值
前row1行(第col1列~第col2列)的值 = 前row1行前col2+1列的值 - 前row1行前col1列的值
sums[row2+1][col2+1] + sums[row1][col1] - sums[row2+1][col1] - sums[row1][col2+1]