每日一题 661. 图片平滑器

272 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目描述

图像平滑器 是大小为 3 x 3 的过滤器,用于对图像的每个单元格平滑处理,平滑处理后单元格的值为该单元格的平均灰度。

每个单元格的平均灰度定义为:该单元格自身及其周围的 8 个单元格的平均值,结果需向下取整。(即,需要计算蓝色平滑器中 9 个单元格的平均值)。

如果一个单元格周围存在单元格缺失的情况,则计算平均灰度时不考虑缺失的单元格(即,需要计算红色平滑器中 4 个单元格的平均值)。

image.jpeg

给你一个表示图像灰度的 m x n 整数矩阵 img ,返回对图像的每个单元格平滑处理后的图像 。

示例

示例1:

image.jpeg

输入:img = [[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

示例2:

image.jpeg

输入: img = [[100,200,100],[200,50,200],[100,200,100]]
输出: [[137,141,137],[141,138,141],[137,141,137]]
解释:
对于点 (0,0), (0,2), (2,0), (2,2): floor((100+200+200+50)/4) = floor(137.5) = 137
对于点 (0,1), (1,0), (1,2), (2,1): floor((200+200+50+200+100+100)/6) = floor(141.666667) = 141
对于点 (1,1): floor((50+200+200+200+200+100+100+100+100)/9) = floor(138.888889) = 138

提示

  • m == img.length
  • n == img[i].length
  • 1 <= m, n <= 200
  • 0 <= img[i][j] <= 255

难度:简单

二、思路分析

众所周知,力扣上,简单题是真简单,中等题有些困难,困难题看不懂答案。 此题为简单题,重拳出击了兄弟们!

题目解析

  1. 题目内容比较长,但实际上比较简单,千万不要被题目吓到。
  2. 平均灰度是只当前坐标自身与周围一圈合法位置的元素加和的平均值,而题目求图片的平滑器就转换成为了求一个数组中所有位置对应的平均灰度,并作为结果二维数组进行返回。
  3. 需要注意的是,数组中的边界元素,如果相邻位置不合法,则剩余合法坐标值计算平均值;计算平均值是要向下取整,在 Java 中,整数的除法计算默认为向下取整,可直接使用。

解题思路

对于求解二维数组中每个值对应的平均灰度二维数组,可以使用以下流程求解

  1. 记录图片对应二维数组的长度,作为m、n,并根据二维长度创建结果数组res;
  2. 在长度m、n的范围内遍历图片二维数组,每个坐标对应一个数值;
  3. 对于遍历获取的每个坐标位置,求当前位置元素的平均灰度
    • 以当前位置作为中心,判断(-1,-1),(-1,0),(-1,1),(0,-1),(0,0),(0,1),(1,-1),(1,0),(1,1)共9个位置;
    • 如果位置合法即属于数组内部,则记录位置 count+1,并使用 sum 累积;
    • 在判断完9个位置后,使用和 sum 除以数量 count,得到向下取整的平均灰度
  4. 整个数组遍历完成后,得到完整的平均灰度结果数组 res,最终返回即可。

三、AC 代码

// 方法获取平滑结果数组
public int[][] imageSmoother(int[][] img) {
    int m = img.length;
    int n = img[0].length;
    int[][] res = new int[m][n];
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            res[i][j] = getValue(img,i,j);
        }
    }
    return res;
}

// 方法获取当前位置平滑值
public int getValue(int[][] img, int i, int j){
    int sum = 0, count = 0;
    int[] direct = new int[]{-1,0,1};
    for(int a = 0; a < 3; a++){
        for(int b = 0; b < 3; b++){
            int x = direct[a] + i, y = direct[b] + j;
            if(x >= 0 && x < img.length && y >=0 && y < img[0].length){
                count++;
                sum += img[x][y];
            }
        }
    }
    return sum / count;
}

四、总结

知识点

  • 本题无知识点,把 for 循环写好即可。

最后

阳春三月,算法刷起来!LeetCode 每日一题