侧边栏壁纸
博主头像
GabrielxD

列車は必ず次の駅へ。では舞台は?私たちは?

  • 累计撰写 471 篇文章
  • 累计创建 108 个标签
  • 累计收到 9 条评论

目 录CONTENT

文章目录

【前缀和】二维区域和检索 - 矩阵不可变

GabrielxD
2022-10-11 / 0 评论 / 0 点赞 / 24 阅读 / 624 字 / 正在检测是否收录...

题目

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


给定一个二维矩阵 matrix,以下类型的多个请求:

  • 计算其子矩形范围内元素的总和,该子矩阵的 左上角(row1, col1)右下角(row2, col2)

实现 NumMatrix 类:

  • NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初始化
  • int sumRegion(int row1, int col1, int row2, int col2) 返回 左上角 (row1, col1) 、右下角 (row2, col2) 所描述的子矩阵的元素 总和

示例 1:

输入: 
["NumMatrix","sumRegion","sumRegion","sumRegion"]
[[[[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]]],[2,1,4,3],[1,1,2,2],[1,2,2,4]]
输出: 
[null, 8, 11, 12]

解释:
NumMatrix numMatrix = new NumMatrix([[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]]);
numMatrix.sumRegion(2, 1, 4, 3); // return 8 (红色矩形框的元素总和)
numMatrix.sumRegion(1, 1, 2, 2); // return 11 (绿色矩形框的元素总和)
numMatrix.sumRegion(1, 2, 2, 4); // return 12 (蓝色矩形框的元素总和)

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 200
  • -10^5 <= matrix[i][j] <= 10^5
  • 0 <= row1 <= row2 < m
  • 0 <= col1 <= col2 < n
  • 最多调用 10^4 次 sumRegion 方法

解题

方法一:前缀和

思路

维护一个二维的前缀和数组(prefSums):

定义 prefSums[i][j] 表示 从 (0,0)(0,0) 位置到 (i,j)(i,j) 位置的子矩形所有元素之和,那么构建前缀和时:

S(O,D)=S(O,C)+S(O,B)S(O,A)+DS(O,D)=S(O,C)+S(O,B)−S(O,A)+D

304.001.jpeg

于是:prefSums[i][j] = prefSums[i - 1][j] + prefSums[i][j - 1] + matrix[i - 1][j - 1] - prefSums[i - 1][j - 1]

算矩形面积时:

S(A,D)=S(O,D)S(O,E)S(O,F)+S(O,G)S(A,D)=S(O,D)−S(O,E)−S(O,F)+S(O,G)

img

于是:ans = prefSums[row2 + 1][col2 + 1] - prefSums[row2 + 1][col1] - prefSums[row1][col2 + 1] + prefSums[row1][col1]

代码

class NumMatrix {
    int[][] prefSums;

    public NumMatrix(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        prefSums = new int[m + 1][n + 1];
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                prefSums[i][j] = prefSums[i - 1][j] + prefSums[i][j - 1] +
                    matrix[i - 1][j - 1] - prefSums[i - 1][j - 1];
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return prefSums[row2 + 1][col2 + 1] - prefSums[row2 + 1][col1] -
            prefSums[row1][col2 + 1] + prefSums[row1][col1];
    }
}
0

评论区