【LeetCode】墙与门(BFS)

【LeetCode】墙与门(BFS)

题目:
你被给定一个 m × n 的二维网格,网格中有以下三种可能的初始化值:

-1 表示墙或是障碍物
0 表示一扇门
INF 无限表示一个空的房间。然后,我们用 231 - 1 = 2147483647 代表 INF。你可以认为通往门的距离总是小于 2147483647 的。
你要给每个空房间位上填上该房间到 最近 门的距离,如果无法到达门,则填 INF 即可。

示例:
给定二维网格:
INF  -1  0  INF
INF INF INF  -1
INF  -1 INF  -1
  0  -1 INF INF
运行完你的函数后,该网格应该变成:
  3  -1   0   1
  2   2   1  -1
  1  -1   2  -1
  0  -1   3   4

思路:


实际上就是找每个房间到最近的门的距离,我们从每个门开始,广度优先搜索并记录层数就行了。如果某个房间之前被标记过距离,那就选择这个距离和当前距离中较小的那个。这题要注意剪枝,如果下一步是门或者下一步是墙或者下一步已经访问过了,就不要加入队列中。否则会超时。


我使用的是利用队列进行BFS广度优先遍历,把门(0)做为起点加入到队列中,然后再把周围可到达的房间加入到队列中。
(1)剪枝:
1.判断是否有数组越界
2.判断是否有重复的遍历(使用HashSet集合)
3.判断这个数组下标的单元下存储的数字是否大于0
(2)剪枝:
判断之前被其它门搜索过的房间步长与现在的这个门的步长谁更佳的短!

代码如下:

public static void wallsAndGates(int[][] rooms) {
		 if(rooms.length==0||rooms[0].length==0||rooms==null)
			 return ;
		 for(int i=0;i<rooms.length;i++)
			 for(int j=0;j<rooms[i].length;j++)
				 if(rooms[i][j]==0)
					 BFS(rooms,i,j);
	 }
	 
	 public static void BFS(int[][] r,int i,int j) {
		 Queue<Integer> queue = new LinkedList<Integer>();
		 Set<Integer> set = new HashSet<Integer>();
		 int dist = 0;
		 //这里的存储方式很好,不仅确保了数据唯一性,这样也便于后面的拆分!
		 queue.add(i*r[i].length+j);
		 set.add(i*r[i].length+j);
		 int size;
		 
		 while(!queue.isEmpty()) {
			 size=queue.size();
			 for(int k=0;k<size;k++) {
				 int target = queue.poll();
				 int row = target/r[i].length;
				 int col = target%r[i].length;
				 
				  //剪枝(2)
				 if(r[row][col]<=dist&&!(r[row][col]==0))
					 continue;
				 r[row][col] = Math.min(r[row][col],dist);
				 int up = row-1;
				 int down = row+1;
				 int left = col-1;
				 int right = col+1;
				 
				 //剪枝(1)
				 if(up>=0&&r[up][col]>0&&!(set.contains(up*r[i].length+col))) {
					 queue.add(up*r[i].length+col);
					 set.add(up*r[i].length+col);
				 }
				 if(down<r.length&&r[down][col]>0&&!(set.contains(down*r[i].length+col))) {
					 queue.add(down*r[i].length+col);
					 set.add(down*r[i].length+col);
				 }
				 if(left>=0&&r[row][left]>0&&!(set.contains(row*r[i].length+left))) {
					 queue.add(row*r[i].length+left);
					 set.add(row*r[i].length+left);
				 }
				 if(right<r[row].length&&r[row][right]>0&&!(set.contains(row*r[i].length+right))) {
					 queue.add(row*r[i].length+right);
					 set.add(row*r[i].length+right);
				 }
				 
			 }
			 
			 dist++;
		 }
	
	 }

最重要的是用队列实现BFS的核心思想,还有进行剪枝(减少不必要的执行次数)。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值