【神奇的技巧】leetcode - 661. Image Smoother【整数位信息使用 + 二维数组边界考虑 + 数组的巧妙使用】

题目1:661. Image SmootherGiven a 2D integer matrix M representing the gray scale of an image, you need to design a smoother to make the gray scale of each cell becomes the average gray scale (
摘要由CSDN通过智能技术生成


题目

Given a 2D integer matrix M representing the gray scale of an image, you need to design a smoother to make the gray scale of each cell becomes the average gray scale (rounding down) of all the 8 surrounding cells and itself. If a cell has less than 8 surrounding cells, then use as many as you can.

Example 1:

Input:
[[1,1,1],
 [1,0,1],
 [1,1,1]]
Output:
[[0, 0, 0],
 [0, 0, 0],
 [0, 0, 0]]
Explanation:
For the point (0,0), (0,2), (2,0), (2,2): floor(3/4) = floor(0.75) = 0
For the point (0,1), (1,0), (1,2), (2,1): floor(5/6) = floor(0.83333333) = 0
For the point (1,1): floor(8/9) = floor(0.88888889) = 0

Note:

  1. The value in the given matrix is in the range of [0, 255].
  2. The length and width of the given matrix are in the range of [1, 150].


分析及解答

解法:(简洁
大神: stefanpochmann

I store the sums and counts in the higher bits and divide them in a second pass.

public int[][] imageSmoother(int[][] M) {
    int m = M.length, n = M[0].length;
    for (int i=0; i<m; i++)
        for (int j=0; j<n; j++)
            for (int I=i-1; I<i+2; I++)
                for (int J=j-1; J<j+2; J++)
                    if (I >= 0 && I < m && J >= 0 && J < n)
                        M[i][j] += 256 + M[I][J] % 256 * 4096;
    for (int i=0; i<m; i++)
        for (int j=0; j<n; j++)
            M[i][j] = M[i][j] / 4096 / (M[i][j] / 256 % 16);
    return M;
}

After my first pass, each M[i][j] holds:

  • In bits 0-7: The original value.
  • In bits 8-11: The number of contributing cells (i.e., the number of neighbors, plus 1 (for the cell itself)). That's why I add 256 for each contributing cell.
  • In bits 12-31: The sum of the original values of the contributing cells. That's why I add the original value of M[I][J] times 4096.

解法:(下面反例的改进)

class Solution {
    public int[][] imageSmoother(int[][] M) {
         if(M==null || M.length<1){
             return null;
         }
         int[][] array = new int[M.length][M[0].length];
         int[][] dirs = new int[][]{{-1,0},{1,0},{0,1},{0,-1},{-1,-1},{-1,1},{1,1},{1,-1}};//巧妙的数组设置。
         for(int i=0;i<M.length;i++){
             for(int j=0;j<M[0].length;j++){
                 int sum=M[i][j];
                 int count =1;
                 for(int [] dir:dirs){  //使用数组。
                     int x=i+dir[0];
                     int y=j+dir[1];
                     if(x<0 || x>=M.length || y<0 || y>=M[0].length){  //判断四周的数组是否有效。
                         continue;
                     }else{
                         count++;
                         sum+=M[x][y];
                     }
                 }
                 
                 array[i][j] = sum/count;
             }
         }
        
         return array;
    }
}


解法:(反例:垃圾的算法)

分为好几次遍历:

* 每个元素影响其下面的元素。

*每个元素影响其上面的元素。

*每个元素影响其斜对角的元素。

class Solution {

    public int[][] imageSmoother(int[][] M) {
    	
    	if(M.length == 1 && M[0].length == 1){
    		return M;
    	}
        //1.让每个results中的单元,保留周围元素的和。
        int results[][] = new int[M.length][M[0].length];
        for(int i = 0; i < M.length ; i++){
        	for(int j = 0; j < M[0].length ;j++){
        		results[i][j] = M[i][j];
        	}
        	}
        // 从左向右
        for(int i = 0; i < M.length ; i++){
        	for(int j = 0; j < M[0].length ;j++){
        		if(i < M.length -1){
        			results[i+1][j] += M[i][j];
        		}
        		if(j < M[0].length-1){
        			results[i][j+1] += M[i][j];
        			
        		}
        		if(i < M.length -1 && j < M[0].length-1){
        			results[i+1][j+1] += M[i][j];
        		}
        	}
        }
        
        //从右向左,每个节点去影响周围的元素。
        for(int i = M.length -1; i >= 0;i--){
        	for(int j = M[0].length - 1; j >= 0;j--){
        		if(i > 0){
        			results[i-1][j] += M[i][j];
        		}
        		if(j > 0){
        			results[i][j-1] += M[i][j];
        		if(i > 0 && j > 0){
        			results[i-1][j-1] += M[i][j];
        		}
        	}
        }
    }
        //影响斜对角。
        for(int i = 0; i < M.length ; i++){
        	for(int j = 0; j < M[0].length ;j++){
        		if(i+1 <= M.length -1 && j-1 >= 0){
        			results[i+1][j-1] += M[i][j];
        		}
        		
        		if(i-1 >=0 && j+1 <= M[0].length -1){
        			results[i-1][j+1] += M[i][j];
        		}
        	}}
        
        //2.计算平均值。
        for(int i = 0; i < M.length ; i++){
        	for(int j = 0; j < M[0].length ;j++){
        	int	count = 9;//记录周围元素的数量
            int row = 0;
        	if(i == 0){
        		count -= 3;//顶行,去除3个元素
        		row++;
        	}
        	if(i == M.length-1){
        		count -= 3;//最底行,去除3个元素
        		row++;
        	}
        	
        	if(j == 0){
        		count -=3;//最左列,去除3个元素
        		count += row;//加上多去的。(行与列产生了交叉)
        	}
        	if(j == M[0].length-1){
        		count -= 3;
        		count += row;
        	}
        	results[i][j] = results[i][j]/count;
        	}
        	}
        return results;
}

}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值