您的位置:首页 > 其它

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

2017-08-20 16:55 561 查看

题目

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:

The value in the given matrix is in the range of [0, 255].
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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: