这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战
题目
给你一个 * 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:
- i - k <= r <= i + k
- j - k <= c <= j + k
- (r, c) 在矩阵内。
示例
输入: mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出: [[12,21,16],[27,45,33],[24,39,28]]
输入: mat = [[1,2,3],[4,5,6],[7,8,9]], k = 2
输出: [[45,45,45],[45,45,45],[45,45,45]]
提示
m == mat.lengthn == mat[i].length1 <= m, n, k <= 1001 <= mat[i][j] <= 100
解题思路
类似的矩阵区域和的题目,我们大多都可以使用前缀和的方法来进行实现:
- 先定义一个矩阵,登记矩阵对应位置的前缀和:
pre[mat.length + 1][mat[0].length + 1]pre[i + 1][j + 1] = pre[i + 1][j] + pre[i][j + 1] - pre[i][j] + mat[i][j]- 左边的矩阵面积 + 上边的矩阵面积 - 两矩阵覆盖的面积 + 当前元素值
- 通过前缀和快速求得区间和:
- 得到矩阵坐标
[(i - k, j - k), (i + k, j + k)] - 减掉上边界的面积
- 减掉左边界的面积
- 加上被多次扣减的覆盖面积
- 得到矩阵坐标
代码实现
class Solution {
public int[][] matrixBlockSum(int[][] mat, int k) {
int[][] pre = new int[mat.length + 1][mat[0].length + 1];
for (int i = 0; i < mat.length; i++) {
for (int j = 0; j < mat[0].length; j++) {
// 前缀和统计
pre[i + 1][j + 1] = pre[i][j + 1] + pre[i + 1][j] - pre[i][j] + mat[i][j];
}
}
int[][] ret = new int[mat.length][mat[0].length];
for (int i = 0; i < mat.length; i++) {
for (int j = 0; j < mat[0].length; j++) {
// 获取区间坐标
int r1 = (i - k) >= 0 ? i - k : 0;
int c1 = (j - k) >= 0 ? j - k : 0;
int r2 = (i + k) < mat.length ? i + k : mat.length - 1;
int c2 = (j + k) < mat[0].length ? j + k : mat[0].length - 1;
// 求得矩阵区域和
ret[i][j] = pre[r2 + 1][c2 + 1] - pre[r1][c2 + 1] - pre[r2 + 1][c1] + pre[r1][c1];
}
}
return ret;
}
}
复杂度分析
- 时间复杂度:
- 空间复杂度:
最后
文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!
如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!