1
1   0   2   0   1

0   0   0   0   0

0   0   1   0   0

第一个building, 把涂色把0变成-1, 同一层最终会涂成相同颜色-1

  1    -1    2   -1    1  

 -1    -1   -1   -1   -1

 -1    -1    1   -1   -1

距离矩阵

0   1   0   5   0

1   2   3   4   5

2   3   0   5   6

第一个building, 把涂色把-1变成-2, 同一层最终会涂成相同颜色-2

  1    -2    2   -2    1  

 -2    -2   -2   -2   -2

 -2    -2    1   -2   -2

距离矩阵

0   6   0   6   0

6   6   6   6   6

8   8   0   8   8

第一个building, 把涂色把-2变成-3, 同一层最终会涂成相同颜色-3

  1    -3    2   -3    1  

 -3    -3   -3   -3   -3

 -3    -3    1   -3   -3

距离矩阵

0    9    0   9   0

9    8    7   8   9

10   9    0   9   10

为了避路径重复,我们有两种方法,一种是用额外的空间visited, 一种是改变输入。
从第一个点出发0表示空地,-1表示已经走过的空地,避免重复。
从第二个点出发-1表示空地,-2表示已经走过的空地,避免重复。
看起来就像一层层的涂色。

public class Solution {
    private int[] dx = {0, 1, 0, -1},  dy = {1, 0, -1, 0};
    private int min = Integer.MAX_VALUE;
    
    public int shortestDistance(int[][] grid) {
        if(grid == null || grid.length == 0) return 0;
        int m = grid.length, n = grid[0].length;
        int[][] distance = new int[m][n];                   // 记录累加距离
        int start = 0;
        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(grid[i][j] == 1)                         //入口
                    bfs(grid, distance, i, j, start--);     //每次涂色之后,换另一种颜色
            }
        }
        
        return min == Integer.MAX_VALUE ? -1 : min;
    }
    
    public void bfs(int[][] grid, int[][] distance, int i, int j, int start){
         ArrayDeque<int[]> q = new ArrayDeque<>();
         q.offer(new int[]{i,j});                           
         int level = 0, m = grid.length, n = grid[0].length;
         min = Integer.MAX_VALUE;
         
         while(!q.isEmpty()){
             int size = q.size();                       // 涂色的时候,记录当前层的大小
             level++;                                   // 进入下一层,需要增加距离
             for(int k=0; k<size; k++){ 
                 int[] node = q.poll();
                 for(int pos=0; pos<4; pos++){
                     int x = node[0] + dx[pos];
                     int y = node[1] + dy[pos];         // 只会走空地,!=1, !=2的地方
                     if(x>=0 && y>=0 && x<m && y<n && grid[x][y] == start){
                         q.offer(new int[]{x, y});
                         grid[x][y] = start-1;          // 涂色,可以用vistied[][]代替
                         distance[x][y] += level;       // 累加距离
                         min = Math.min(min, distance[x][y]);       //记录最值,实际上最后一个building给出的结果才有意义
                     }
                 }
             }
             
         }
         
    }
}

大米中的大米
12 声望5 粉丝

你的code是面向面试编程的,收集和整理leetcode discussion里个人认为的最优且最符合我个人思维逻辑的解法。


« 上一篇
LFU
下一篇 »
425 Word Squares