Leetcode: Walls and Gates

You are given a m x n 2D grid initialized with these three possible values.

-1 - A wall or an obstacle.
0 - A gate.
INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 to represent INF as you may assume that the distance to a gate is less than 2147483647.
Fill each empty room with the distance to its nearest gate. If it is impossible to reach a gate, it should be filled with INF.

For example, given the 2D grid:
INF  -1  0  INF
INF INF INF  -1
INF  -1 INF  -1
  0  -1 INF INF
After running your function, the 2D grid should be:
  3  -1   0   1
  2   2   1  -1
  1  -1   2  -1
  0  -1   3   4

實際上就是找每一個房間到最近的門的距離,咱們從每一個門開始,廣度優先搜索並記錄層數就好了。若是某個房間以前被標記過距離,那就選擇這個距離和當前距離中較小的那個。這題要注意剪枝,若是下一步是門或者下一步是牆或者下一步已經訪問過了,就不要加入隊列中。不然會超時。less

 1 public class Solution {
 2     int[][] dir = new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
 3     
 4     public void wallsAndGates(int[][] rooms) {
 5         if (rooms==null || rooms.length==0 || rooms[0].length==0) return;
 6         int m = rooms.length;
 7         int n = rooms[0].length;
 8         for (int i=0; i<m; i++) {
 9             for (int j=0; j<n; j++) {
10                 if (rooms[i][j] != 0) continue;
11                 LinkedList<Integer> queue = new LinkedList<Integer>();
12                 boolean[][] visited = new boolean[m][n];
13                 queue.offer(i*n + j);
14                 visited[i][j] = true;
15                 int pNum = 1;
16                 int cNum = 0;
17                 int level = 0;
18                 while (!queue.isEmpty()) {
19                     int cur = queue.poll();
20                     int row = cur/n;
21                     int col = cur%n;
22                     pNum--;
23                     for (int[] d : dir) {
24                         int x = row + d[0];
25                         int y = col + d[1];
26                         if (x>=0 && x<m && y>=0 && y<n && !visited[x][y] && rooms[x][y]!=0 && rooms[x][y]!=-1) {
27                             rooms[x][y] = Math.min(rooms[x][y], level+1);
28                             queue.offer(x*n+y);
29                             visited[x][y] = true;
30                             cNum++;
31                         }
32                     }
33                     if (pNum == 0) {//finish this level
34                         level++;
35                         pNum = cNum;
36                         cNum = 0;
37                     }
38                 }
39             }
40         }
41     }
42 }

BFS 還有一種寫法,就是不用pNum, cNum兩個variables, 而記錄每一次queue的size,而後poll() size那麼屢次,其實本質是同樣的this

 1 public class Solution {
 2     public void wallsAndGates(int[][] rooms) {
 3         if(rooms.length == 0) return;
 4         for(int i = 0; i < rooms.length; i++){
 5             for(int j = 0; j < rooms[0].length; j++){
 6                 // 若是遇到一個門,從門開始廣度優先搜索,標記連通的節點到本身的距離
 7                 if(rooms[i][j] == 0) bfs(rooms, i, j);
 8             }
 9         }
10     }
11     
12     public void bfs(int[][] rooms, int i, int j){
13         Queue<Integer> queue = new LinkedList<Integer>();
14         queue.offer(i * rooms[0].length + j);
15         int dist = 0;
16         // 用一個集合記錄已經訪問過的點
17         Set<Integer> visited = new HashSet<Integer>();
18         visited.add(i * rooms[0].length + j);
19         while(!queue.isEmpty()){
20             int size = queue.size();
21             // 記錄深度的搜索
22             for(int k = 0; k < size; k++){
23                 Integer curr = queue.poll();
24                 int row = curr / rooms[0].length;
25                 int col = curr % rooms[0].length;
26                 // 選取以前標記的值和當前的距離的較小值
27                 rooms[row][col] = Math.min(rooms[row][col], dist);
28                 int up = (row - 1) * rooms[0].length + col;
29                 int down = (row + 1) * rooms[0].length + col;
30                 int left = row * rooms[0].length + col - 1;
31                 int right = row * rooms[0].length + col + 1;
32                 if(row > 0 && rooms[row - 1][col] > 0 && !visited.contains(up)){
33                     queue.offer(up);
34                     visited.add(up);
35                 }
36                 if(col > 0 && rooms[row][col - 1] > 0 && !visited.contains(left)){
37                     queue.offer(left);
38                     visited.add(left);
39                 }
40                 if(row < rooms.length - 1 && rooms[row + 1][col] > 0 && !visited.contains(down)){
41                     queue.offer(down);
42                     visited.add(down);
43                 }
44                 if(col < rooms[0].length - 1 && rooms[row][col + 1] > 0 && !visited.contains(right)){
45                     queue.offer(right);
46                     visited.add(right);
47                 }
48             }
49             dist++;
50         }
51     }
52 }
相關文章
相關標籤/搜索