LeetCode 661. 图片平滑器
题目描述
解题思路
前缀和
本题本质上计算矩阵的区域和,类似于LeetCode 1314. 矩阵区域和。
preSum[i][j]
表示矩阵img中以(0, 0)
为左上角,(i-1, j-1)
为右下角的矩阵和。即preSum[0][0] = 0
;
计算以(i - k, j - k)
为左上角和(i + k, j + k)
为右上角的矩阵区域和,可直接通过计算
sum = preSum[i + k + 1][j + k + 1] - preSum[i - k][j + k + 1] - preSum[i + k + 1][j - k] + preSum[i - k][j - k]
本题计算的是每个单元格自身及其周围的 8 个单元格组成矩阵的和值,可通过计算四个边界值围成的区域和,再除以该区域中元素的总个数,即可得到平均值,即平均灰度。
注意可能会存在下标超出矩阵范围,可将所有的横坐标与row - 1
取较小值,纵坐标与col - 1
取较小值,再将所有坐标与0
取较大值。
class Solution {
int[][] preSum;
public int[][] imageSmoother(int[][] img) {
//前缀和
int row = img.length;
int col = img[0].length;
int[][] ret = new int[row][col];
//以(0,0)为左上角 (i-1,j-1)为右下角的矩阵元素和
preSum = new int[row+1][col+1];
for(int i = 1; i <= row; i ++){
for(int j = 1; j <= col; j ++){
preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1] - preSum[i - 1][j - 1] + img[i - 1][j - 1];
}
}
for(int i = 0; i < row; i ++){
for(int j = 0; j < col; j ++){
//l 左边界 r 右边界 u 上边界 d 下边界
int l = Math.max(0, j - 1), r = Math.min(col - 1, j + 1), u = Math.min(row - 1, i + 1), d = Math.max(0, i - 1);
ret[i][j] = (preSum[u + 1][r + 1] - preSum[u + 1][l] - preSum[d][r + 1] + preSum[d][l]) / ((r - l + 1) * (u - d + 1));
}
}
return ret;
}
}
复杂度分析
- 时间复杂度:
O(row*col)
row为矩阵的行数,col为矩阵的列数。 - 空间复杂度:
O(row*col)
前缀和数组preSum所需要的空间。