Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 1314. Matrix Block Sum #1314

Open
grandyang opened this issue May 30, 2019 · 1 comment
Open

[LeetCode] 1314. Matrix Block Sum #1314

grandyang opened this issue May 30, 2019 · 1 comment

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

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 同步地址:

#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 题目讲解汇总(持续更新中...)

(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,快快加入吧~)

知识星球 喜欢请点赞,疼爱请打赏❤️~.~

微信打赏

|

Venmo 打赏


---|---

@mingyEx
Copy link

mingyEx commented Jan 22, 2022

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

现在有了,快来做。
我看不懂题意呜呜呜 =_=

@grandyang grandyang changed the title [LeetCode] 1314. Missing Problem [LeetCode] 1314. Matrix Block Sum Nov 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants