🚩传送门:https://leetcode-cn.com/problems/image-smoother/
题目
包含整数的二维矩阵 M 表示一个图片的灰度。你需要设计一个平滑器来让每一个单元的灰度成为平均灰度 (向下舍入) ,平均灰度的计算是周围的 8
个单元和它本身的值求平均,如果周围的单元格不足八个,则尽可能多的利用它们。
示例 :
输入: [[1,1,1], [1,0,1], [1,1,1]] 输出: [[0, 0, 0], [0, 0, 0], [0, 0, 0]] 解释: 对于点
(0,0), (0,2), (2,0), (2,2)
: 平均(3/4)
= 平均(0.75) = 0
对于点(0,1), (1,0), (1,2), (2,1)
: 平均(5/6)
= 平均(0.83333333) = 0
对于点(1,1)
: 平均(8/9)
= 平均(0.88888889) = 0
解题思路:遍历矩阵
对于矩阵中的每一个单元格,找所有 9
个包括它自身在内的紧邻的格子。
将所有邻居的和保存在 ans[r][c]
中,同时记录邻居的数目 count
。最终的答案就是和除以邻居数目。
复杂度分析
时间复杂度:,其中
是图片中像素的数目。我们需要将每个像素都遍历一遍。
空间复杂度: ,我们答案的大小。
官方代码
class Solution {
public int[][] imageSmoother(int[][] M) {
//1.获取矩阵 M 的行列数
int R = M.length, C = M[0].length;
int[][] ans = new int[R][C];
//2.依次遍历行
for (int r = 0; r < R; ++r)
//3.依次遍历列
for (int c = 0; c < C; ++c) {
int count = 0;
//4.自身为中,遍历上种下三行
for (int nr = r-1; nr <= r+1; ++nr)
//5.自身为中,遍历左中右三列
for (int nc = c-1; nc <= c+1; ++nc) {
//6.检查是否在合法区域
if (0 <= nr && nr < R && 0 <= nc && nc < C) {
ans[r][c] += M[nr][nc];
count++;
}
}
//7.计算当前元素的灰度
ans[r][c] /= count;
}
return ans;
}
}
👀解题思路:设置偏移标志数组
直接计算周围的 8
个单元和它本身的值求平均即可。
复杂度分析
时间复杂度:,其中
是图片中像素的数目。我们需要将每个像素都遍历一遍。
空间复杂度: ,我们答案的大小。
官方代码
class Solution {
int row = 0;
int col = 0;
public int[][] imageSmoother(int[][] M) {
//1.判断无效 M 矩阵
if (M == null || M.length < 1 || M[0] == null || M[0].length < 1) {
return null;
}
//2.标记矩阵 M 的行数和列数
row = M.length;
col = M[row - 1].length;
//3.创建答案数组
int ans[][] = new int[row][col];
//4.依次遍历每一个元素,进行平滑计算
for (int i = 0;i < row;i++) {
for (int j = 0;j < col;j++) {
//5.保存答案
ans[i][j] = calcul(M,i,j);
}
}
//6.返回结果
return ans;
}
//#标记数组上、下、左、右,上左、上右、下左、下右
int dirR[] = {-1,1,0,0,-1,-1,1,1};
int dirC[] = {0,0,-1,1,-1,1,-1,1};
private int calcul(int arr[][],int i,int j) {
//1.中心点
int count = 1;
int sum = arr[i][j];
//2.遍历四周
for (int k = 0;k < dirR.length;k++) {
//3.坐标偏移
int nextR = i + dirR[k];
int nextC = j + dirC[k];
//4.确认是否在合法区域内
if (nextR >= 0 && nextR < row && nextC >= 0 && nextC < col) {
//5.加上当前点
count++;
sum += arr[nextR][nextC];
}
}
//6.计算结果返回
return sum / count;
}
}