现在开始一天一题了,防止老年痴呆 = =
一、题目大意
给你一个 m * n 的矩阵 mat 和一个整数 K ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:
i - K <= r <= i + K, j - K <= c <= j + K
(r, c) 在矩阵内。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/matrix-block-sum
二、题目思路以及AC代码
这题读懂题之后,我第一个思路就是暴力(好长时间没做题的后果),其实就是要算矩阵里针对每个位置,上下左右位移K的子矩阵的元素和,直接暴力的时间复杂度是O(N2K2),比较简单直接。
然后是想到了二维前缀和,即提前计算出一个矩阵prefix,其中prefix[i][j]代表以(i, j)为右下角,以(0, 0)为左上角的矩阵的元素和,这样的话,我们在计算区域和的时候,就可以直接利用以下公式进行计算。
当然, 这里要注意i+K,j+K,j-K-1,i-K-1的范围,不能超过矩阵大小,也不能小于0,这处理起来还是挺费劲的,可以参考我代码中的处理方式,在前缀和中添加冗余的行和列用于辅助处理。
下面给出AC代码:
class Solution {
public:
vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int K) {
vector<vector<int>> res;
int rows = mat.size();
if (rows == 0) return res;
int cols = mat[0].size();
if (cols == 0) return res;
// 求前缀和
int prefix[rows+1][cols+1];
for (int i=0;i<=rows;i++) {
for (int j=0;j<=cols;j++) {
prefix[i][j] = 0;
}
}
for (int i=1;i<=rows;i++) {
for (int j=1;j<=cols;j++) {
prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1] + mat[i-1][j-1];
}
}
// 计算区域和
for (int i=0;i<rows;i++) {
vector<int> row;
for (int j=0;j<cols;j++) {
int up = max(-1, i - K - 1);
int down = min(rows - 1, i + K);
int left = max(-1, j - K - 1);
int right = min(cols - 1, j + K);
row.push_back(prefix[down+1][right+1] - prefix[down+1][left+1] - prefix[up+1][right+1] + prefix[up+1][left+1]);
}
res.push_back(row);
}
return res;
}
};