题目描述:
图像平滑器 是大小为 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;
}
思路差不多,大概看看就能理解