🚩传送门: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。最终的答案就是和除以邻居数目。

复杂度分析

时间复杂度:[LeetCode]Ar661. 图片平滑器 - 图1,其中 [LeetCode]Ar661. 图片平滑器 - 图2 是图片中像素的数目。我们需要将每个像素都遍历一遍。

空间复杂度:[LeetCode]Ar661. 图片平滑器 - 图3 ,我们答案的大小。

官方代码

  1. class Solution {
  2. public int[][] imageSmoother(int[][] M) {
  3. //1.获取矩阵 M 的行列数
  4. int R = M.length, C = M[0].length;
  5. int[][] ans = new int[R][C];
  6. //2.依次遍历行
  7. for (int r = 0; r < R; ++r)
  8. //3.依次遍历列
  9. for (int c = 0; c < C; ++c) {
  10. int count = 0;
  11. //4.自身为中,遍历上种下三行
  12. for (int nr = r-1; nr <= r+1; ++nr)
  13. //5.自身为中,遍历左中右三列
  14. for (int nc = c-1; nc <= c+1; ++nc) {
  15. //6.检查是否在合法区域
  16. if (0 <= nr && nr < R && 0 <= nc && nc < C) {
  17. ans[r][c] += M[nr][nc];
  18. count++;
  19. }
  20. }
  21. //7.计算当前元素的灰度
  22. ans[r][c] /= count;
  23. }
  24. return ans;
  25. }
  26. }

👀解题思路:设置偏移标志数组

直接计算周围的 8 个单元和它本身的值求平均即可。

复杂度分析

时间复杂度:[LeetCode]Ar661. 图片平滑器 - 图4,其中 [LeetCode]Ar661. 图片平滑器 - 图5 是图片中像素的数目。我们需要将每个像素都遍历一遍。

空间复杂度:[LeetCode]Ar661. 图片平滑器 - 图6 ,我们答案的大小。

官方代码

  1. class Solution {
  2. int row = 0;
  3. int col = 0;
  4. public int[][] imageSmoother(int[][] M) {
  5. //1.判断无效 M 矩阵
  6. if (M == null || M.length < 1 || M[0] == null || M[0].length < 1) {
  7. return null;
  8. }
  9. //2.标记矩阵 M 的行数和列数
  10. row = M.length;
  11. col = M[row - 1].length;
  12. //3.创建答案数组
  13. int ans[][] = new int[row][col];
  14. //4.依次遍历每一个元素,进行平滑计算
  15. for (int i = 0;i < row;i++) {
  16. for (int j = 0;j < col;j++) {
  17. //5.保存答案
  18. ans[i][j] = calcul(M,i,j);
  19. }
  20. }
  21. //6.返回结果
  22. return ans;
  23. }
  24. //#标记数组上、下、左、右,上左、上右、下左、下右
  25. int dirR[] = {-1,1,0,0,-1,-1,1,1};
  26. int dirC[] = {0,0,-1,1,-1,1,-1,1};
  27. private int calcul(int arr[][],int i,int j) {
  28. //1.中心点
  29. int count = 1;
  30. int sum = arr[i][j];
  31. //2.遍历四周
  32. for (int k = 0;k < dirR.length;k++) {
  33. //3.坐标偏移
  34. int nextR = i + dirR[k];
  35. int nextC = j + dirC[k];
  36. //4.确认是否在合法区域内
  37. if (nextR >= 0 && nextR < row && nextC >= 0 && nextC < col) {
  38. //5.加上当前点
  39. count++;
  40. sum += arr[nextR][nextC];
  41. }
  42. }
  43. //6.计算结果返回
  44. return sum / count;
  45. }
  46. }