持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
最近一直在力扣刷题,也逐渐对各类题型有了自己的理解,所谓见招拆招,将自己的浅显经验分享一下,帮助更多在编程路上的朋友们。
矩阵区域和
给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:
i - k <= r <= i + k,j - k <= c <= j + k且(r, c)在矩阵内。
示例 1:
输入: mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出: [[12,21,16],[27,45,33],[24,39,28]]
示例 2:
输入: 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
思路
要求一个区域内所有元素的和,如果暴力求解的话会非常耗时,所以采用前缀和的方法。
对于二维数组的前缀和,求的是当前位置左上方所有元素的和。在初始化前缀和数组时,只需要将其上方和左方的前缀和加起来,再减去左上方的前缀和,加上当前位置元素即可。
在求区域和时,也是同理,要获取当前区域和,需要右下角的前缀和 - 左边界前缀和 - 上边界前缀和 + 左上角前缀和。
题解
class Solution {
public int[][] matrixBlockSum(int[][] mat, int k) {
int m = mat.length;
int n = mat[0].length;
int[][] preSum = new int[m + 1][n + 1];
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
preSum[i + 1][j + 1] = preSum[i][j + 1] + preSum[i + 1][j] - preSum[i][j] + mat[i][j];
}
}
int[][] ans = new int[m][n];
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
int pi = 1 + (i + k >= m? m - 1: i + k);
int pj = 1 + (j + k >= n? n - 1: j + k);
int ni = i - k < 0? 0: i - k;
int nj = j - k < 0? 0: j - k;
ans[i][j] = preSum[pi][pj] - preSum[ni][pj] - preSum[pi][nj] + preSum[ni][nj];
}
}
return ans;
}
}