ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[LeetCode] 1314. Matrix Block Sum 矩阵区域和

2022-08-17 14:03:53  阅读:153  来源: 互联网

标签:1314 Matrix Sum 45 sums 正方形 数组 区间 mat



Given a m x n matrix mat and an integer k, return a matrix answer where each answer[i][j] is the sum of all elements mat[r][c] for:

  • i - k <= r <= i + k,
  • j - k <= c <= j + k, and
  • (r, c) is a valid position in the matrix.

Example 1:

Input: mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1
Output: [[12,21,16],[27,45,33],[24,39,28]]

Example 2:

Input: mat = [[1,2,3],[4,5,6],[7,8,9]], k = 2
Output: [[45,45,45],[45,45,45],[45,45,45]]

Constraints:

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n, k <= 100
  • 1 <= mat[i][j] <= 100

这道题给了一个 m by n 的二维数组 mat 和一个正整数k,现在让返回一个 answer 数组,使得 answer[i][j] 是原数组 mat 中以 (i, j) 为中心,2k+1 为边长的正方形区域的数字之和。英文原版题目表示的不太容易理解,但是可以根据给定的例子来验证自己的理解,美中不足的是例子中没有提供分析,难怪论坛上有人吐槽说看不懂题意。由于 (i, j) 的位置和k的大小不确定,所以这个正方形大小不确定,若 (i, j) 在边缘位置,则边长为k的正方形区域就会缺失一些数字,比如例子1。还有就是若k比较大,则每个位置的正方形区域有可能都涵盖了整个 mat 数组,则所有位置的值都是原 mat 数组的所有数字之和,比如例子2。

其实这道题的本质就是要快速的计算任意一个区间和,也就是要建立二维的累加和数组,对于一维数组计算任意子数组的方法,想必大家都比较熟悉,这里二维的原理也是一样,只不过计算方法上稍稍复杂一些。为了更好的处理边界,这里使用一个 m+1 by n+1 的二维数组 sums 来表示累加和数组,对于某个 (i, j) 位置的更新方法是其在 mat 中对应位置上的值加上 sums[i-1][j] 和 sums[i][j-1],并减去 sums[i-1][j-1]。更新完了累加和数组,就可以来快速计算任意区间和了,要求的正方形区域中心位置是 (i, j),边长是 2k+1,现在要计算出正方形区间的右下顶点和左上顶点。

由于前面提到了这个正方形区间可能不会完全存在,即当中心点位于 mat 数组的边缘时,那么就一定有一部分是不存在的,所以要找出该正方形区间映射到 mat 数组上的区间。该正方形区间的右下顶点的坐标为 (i+k, j+k),但是这个坐标不能超过 mat 数组的最右下角 (m-1, n-1),所以正确的右下顶点坐标为 (min(m-1, i+k), min(n-1, j+k))。同理,该正方形区间的左上顶点的坐标为 (i-k, j-k),但是这个坐标不能小于 mat 数组的最左上角 (0, 0),所以正确的左上顶点坐标为 (max(0, i-k), max(0, j-k)),知道了子区间的左上和右下点的位置,就可以利用累加和数组快速求出区间和了,假设左上顶点坐标为 (p, q),右下顶点坐标为 (x, y),则区间和应该为 sums[x + 1][y + 1] - sums[x + 1][q] - sums[p][y + 1] + sums[p][q],参见代码如下:


class Solution {
public:
    vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
        int m = mat.size(), n = mat[0].size();
        vector<vector<int>> sums(m + 1, vector<int>(n + 1)), res(m, vector<int>(n));
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                sums[i][j] = mat[i - 1][j - 1] + sums[i - 1][j] + sums[i][j - 1] - sums[i - 1][j - 1];
            }
        }
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                int x = min(m - 1, i + k), y = min(n - 1, j + k);
                int p = max(0, i - k), q = max(0, j - k);
                res[i][j] = sums[x + 1][y + 1] - sums[x + 1][q] - sums[p][y + 1] + sums[p][q];
            }
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1314


类似题目:

Stamping the Grid


参考资料:

https://leetcode.com/problems/matrix-block-sum/

https://leetcode.com/problems/matrix-block-sum/discuss/500833/C%2B%2B-prefix-sum-with-explanation

https://leetcode.com/problems/matrix-block-sum/discuss/477041/Java-Prefix-sum-with-Picture-explain-Clean-code-O(m*n)


LeetCode All in One 题目讲解汇总(持续更新中...)

标签:1314,Matrix,Sum,45,sums,正方形,数组,区间,mat
来源: https://www.cnblogs.com/grandyang/p/16594900.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有