标签:
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
实际上就是找每个房间到最近的门的距离,我们从每个门开始,广度优先搜索并记录层数就行了。如果某个房间之前被标记过距离,那就选择这个距离和当前距离中较小的那个。这题要注意剪枝,如果下一步是门或者下一步是墙或者下一步已经访问过了,就不要加入队列中。否则会超时。
1 public class Solution { 2 public void wallsAndGates(int[][] rooms) { 3 if (rooms==null || rooms.length==0 || rooms[0].length==0) return; 4 int m = rooms.length; 5 int n = rooms[0].length; 6 for (int i=0; i<m; i++) { 7 for (int j=0; j<n; j++) { 8 if (rooms[i][j] != 0) continue; 9 LinkedList<Integer> queue = new LinkedList<Integer>(); 10 boolean[][] visited = new boolean[m][n]; 11 queue.offer(i*n + j); 12 visited[i][j] = true; 13 int pNum = 1; 14 int cNum = 0; 15 int level = 0; 16 while (!queue.isEmpty()) { 17 int cur = queue.poll(); 18 int row = cur/n; 19 int col = cur%n; 20 pNum--; 21 if (row>0 && rooms[row-1][col]!=0 && rooms[row-1][col]!=-1 && !visited[row-1][col]) { 22 rooms[row-1][col] = Math.min(rooms[row-1][col], level+1); 23 queue.offer((row-1)*n+col); 24 visited[row-1][col] = true; 25 cNum++; 26 } 27 if (row<m-1 && rooms[row+1][col]!=0 && rooms[row+1][col]!=-1 && !visited[row+1][col]) { 28 rooms[row+1][col] = Math.min(rooms[row+1][col], level+1); 29 queue.offer((row+1)*n+col); 30 visited[row+1][col] = true; 31 cNum++; 32 } 33 if (col>0 && rooms[row][col-1]!=0 && rooms[row][col-1]!=-1 && !visited[row][col-1]) { 34 rooms[row][col-1] = Math.min(rooms[row][col-1], level+1); 35 queue.offer(row*n+col-1); 36 visited[row][col-1] = true; 37 cNum++; 38 } 39 if (col<n-1 && rooms[row][col+1]!=0 && rooms[row][col+1]!=-1 && !visited[row][col+1]) { 40 rooms[row][col+1] = Math.min(rooms[row][col+1], level+1); 41 queue.offer(row*n+col+1); 42 visited[row][col+1] = true; 43 cNum++; 44 } 45 if (pNum == 0) {//finish this level 46 level++; 47 pNum = cNum; 48 cNum = 0; 49 } 50 } 51 } 52 } 53 } 54 }
BFS 还有一种写法,就是不用pNum, cNum两个variables, 而记录每一次queue的size,然后poll() size那么多次,其实本质是一样的
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 }
标签:
原文地址:http://www.cnblogs.com/EdwardLiu/p/5077950.html