《LeetCode刷题》661. 图片平滑器(java篇)

20 篇文章 0 订阅
20 篇文章 0 订阅
博客讨论了一道关于图像平滑处理的LeetCode题目,提供了两种不同的解决方案。第一种利用try-catch处理边界情况,虽然可行但效率较低。第二种通过条件判断优化了边界检查,提高了效率。此外,还给出了官方的一种实现方式。
摘要由CSDN通过智能技术生成

题目描述:

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

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

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

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

示例 1:

输入: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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/image-smoother
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

-------------------------------------------------------------------------------------------------------------------------------

day5:今天是一道简单题,做过卷积的应该看题目就会有印象,这道题思路也很简单,通过加周围八个数除以个数就可以了,好玩的是我开始通过try-catch来做的,也能实现该算法,就是耗时和内存都挺高的,代码 如下:

①通过try-catch来避免判断:

public static int[][] imageSmoother1(int[][] img) {
        int sum = 0, num = 0, flag = 0;
        int l1 = img.length, l2 = img[0].length;
        int[][] ret = new int[l1][l2];
        for (int i = 0; i < l1; i++) {
            for (int j = 0; j < l2; j++) {
                for (int k = i - 1 ; k <= i+1; k++) {
                    for (int l = j-1 ; l <= j+1; l++) {
                        flag = addNum(img, k, l);
                        if ( flag > -1 ) {
                            sum += flag;
                            num ++ ;
                        }
                    }
                }
                if (num == 0)
                    ret[i][j] = 0;
                else
                    ret[i][j] = sum / num;
            }
            sum = num = 0;
        }
        return ret;
    }

    private static int addNum(int[][] img, int i, int j){
        try {
            return img[i][j];
        }catch (Exception e) {
            return -1;
        }
    }

代码挺简单的,可详看②


②将①的代码优化,将判断在下面嵌套的for循环里面写了

public int[][] imageSmoother(int[][] img) {
        int sum = 0, num = 0;
        int l1 = img.length, l2 = img[0].length;
        int[][] ret = new int[l1][l2];
        for (int i = 0; i < l1; i++) {
            for (int j = 0; j < l2; j++) {
                for (int k = (i - 1) > 0 ? i -1 : 0 ; k <= i+1 && k >= 0 && k < l1; k++) {
                    for (int l = (j-1)> 0 ? j -1 : 0 ; l <= j+1 && l >=0 && l < l2; l++) {
                        sum += img[k][l];
                        num ++ ;
                    }
                }
                ret[i][j] = sum / num;
                sum = num = 0;
            }
        }
        return ret;
    }

 思路如下:sum值定义来判断每个数周围数的总和,num表示周围有几个数,l1表示行数,l2表示列数,ret是卷积后的结果,四个for循环,第一个表示循环i行,第二个表示循环j列,第三个表示该行和它的上下行,第四个表示该列和它的左右列,第三四列中定义介绍:int k = (i-1) > 0 ? i-1 : 0;这里用了三维表达式,当i-1大于0时k等于i-1,不然就等于0;k <= i+1 && k >= 0 && k < l1;判断语句,k最多是下面那一行,并且k不能小于0,也不能比最长行长,最后用sum表示总和,num表示个数,最终用ret接收除值,最终返回即可


③官方和评论的跟我的思路都差不到太多,就是写的判断,稍微更耗时一点,算一个通过判断的贴一下:

public int[][] imageSmoother(int[][] M) {
        int l1=M.length,l2=M[0].length;
        int[][] r=new int[l1][l2];
        for(int i=0;i<l1;i++)
            for(int j=0;j<l2;j++){
                int sum=M[i][j];
                int num=1;
                if(i>0 && j>0)
                    {sum+=M[i-1][j-1];num++;}
                if(i>0)
                    {sum+=M[i-1][j];num++;}
                if(i>0 && j<l2-1)
                    {sum+=M[i-1][j+1];num++;}
                if(j>0)
                    {sum+=M[i][j-1];num++;}
                if(j<l2-1)
                    {sum+=M[i][j+1];num++;}
                if(i<l1-1 && j>0)
                    {sum+=M[i+1][j-1];num++;}
                if(i<l1-1)
                    {sum+=M[i+1][j];num++;}
                if(i<l1-1 && j<l2-1)
                    {sum+=M[i+1][j+1];num++;}
                r[i][j]=sum/num;                
            }
        return r;
    }

思路差不多,大概看看就能理解 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值