286. Walls and Gates
最后更新
二刷
12-Jan-2017
正规做应该是以每个empty room做BFS,最坏的情况是整个地图里全是room。。
值得思考的一个做法是,以每个gate做搜索= =
BFS的话,先搜到的房间肯定是最短距离。
DFS的话,要配合backtrack,按理说BFS快,但是实际结果是DFS简单得一逼。。
DFS的话,每次罪恶的魔爪触及到一个房间,看看房间里的最小距离是多少,如果最小距离比现在要小,就没必要继续伸下去了,因为继续下去所有的结果都不如之前伸到这个房间的魔爪得到的结果好。。
正好-1代表障碍,肯定比当前魔爪长度要小。。
public class Solution {
public void wallsAndGates(int[][] rooms) {
if (rooms.length == 0) return;
for (int i = 0; i < rooms.length; i++) {
for (int j = 0; j < rooms[0].length; j++) {
if (rooms[i][j] == 0) {
dfs(rooms, i, j, 0);
}
}
}
}
public void dfs(int[][] rooms, int i, int j, int distance) {
if (i < 0 || j < 0 || i >= rooms.length || j >= rooms[0].length) return;
// we do not have to have thsi line
if (rooms[i][j] == -1) return;
if (rooms[i][j] < distance) return;
rooms[i][j] = distance;
dfs(rooms, i+1, j, distance+1);
dfs(rooms, i, j+1, distance+1);
dfs(rooms, i-1, j, distance+1);
dfs(rooms, i, j-1, distance+1);
}
}
按理来说,最好的办法应该是BFS。。。
对于BFS来说,也是分别从每个GATE伸出魔爪,好处就是第一次碰到某个房间,那这个房间的最小值肯定就是当前魔爪的长度,以后魔爪从别的角度伸过来,不会比现在的结果好。。而从这个地方继续往外伸也不会比第一次从这里伸的好,所以别放到Queue里了。。
另外BFS里上下左右可以用1 0 -1 0 1来做,在做Pocket Gems的题的时候用过了,要记住。。
Time: O(mn)
讨论区的解释是,假如有1个GATE,那么从这个GATE开始遍历所有的格子。
假如有K个GATE,无所谓,因为每个格子只会被遍历一次,第二次来因为结果不如第一次好,没有进queue。。
Space: O(mn) 1个GATE,所有位置进Queue
public class Solution {
public void wallsAndGates(int[][] rooms) {
Queue<int[]> q = new LinkedList<>();
for (int i = 0; i < rooms.length; i++) {
for (int j = 0; j < rooms[0].length; j++) {
if (rooms[i][j] == 0) {
q.offer(new int[] {i, j});
}
}
}
int[] directions = {1, 0, -1, 0, 1};
// 0 ,-1, 0, 1
while (!q.isEmpty()) {
int[] tempLoc = q.poll();
int row = tempLoc[0];
int col = tempLoc[1];
for (int t = 0; t < 4; t++) {
int i = row + directions[t];
int j = col + directions[t+1];
if (i < 0 || j < 0 || i >= rooms.length || j >= rooms[0].length) continue;
if (rooms[i][j] != Integer.MAX_VALUE) continue;
rooms[i][j] = rooms[row][col] + 1;
q.offer(new int[] {i, j});
}
}
}
}
一刷
13-Oct-2016
怎么感觉在哪见到过这道题。
从每个门为起点搜索就行,做DFS。
有效房间如果已有值,比较一下,比当前传入值大才更新并go deeper,题里很贴心地一开始设了MAX INT,方便多了。
public class Solution
{
public void wallsAndGates(int[][] rooms)
{
if(rooms.length == 0) return;
for(int i = 0; i < rooms.length;i++)
for(int j = 0; j < rooms[0].length;j++)
{
if(rooms[i][j] == 0)
helper(rooms,i,j,0);
}
}
public void helper(int[][] rooms, int m, int n, int distance)
{
if(m < 0 || n < 0 || m >= rooms.length || n >= rooms[0].length) return;
if(rooms[m][n] < distance) return;
rooms[m][n] = distance;
helper(rooms,m+1,n,distance+1);
helper(rooms,m,n+1,distance+1);
helper(rooms,m-1,n,distance+1);
helper(rooms,m,n-1,distance+1);
}
}