力扣1091

力扣1091

最直接的DFS

之前通过参数传递grid,发现了一个更简洁的信息传递的写法:

// 共享大块的信息
public:
    vector<vector<int>> grid;
    vector<vector<bool>> visited;
	
	int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        this->grid = grid;
	}

一直报错:

AddressSanitizer:DEADLYSIGNAL 
 ==21==ERROR: AddressSanitizer: 
stack-overflow on address 0x7fffcc741ff8 
(pc 0x0000002a8356 bp 0x000000000008 sp 0x7fffcc741fe0 T0)
 ==21==ABORTING

Address Sanitizer(ASan)是一个快速的内存错误检测工具。从gcc 4.8开始,Address Sanitizer成为gcc的一部分。这个错误是因为 LeetCode 使用了Address Sanitizer检查是否存在无限递归。

顺着以前的惯性思维,认为 visited 是负责剪枝的,暴力DFS 的时候没写上 visited。思考了一阵,后知后觉的发现,这个迷宫是个无限路径的圈,如果不设置 visited,就是会在里面永远打转,造成无限递归。

所以 deadly signal 的原因不是递归退出条件写错了,而是已经走过的路无限重复造成无穷递归。

为了方便自己记忆,把递归退出条件分为四类:

1 边界退出递归条件:容易理解,写在最前面
2 内容退出和已经访问递归条件:判断这个格子是不是有致死物,粮食用尽,或者路径不通
3 已经访问退出条件:至少在这条路径里面,要保证不能走回头路
4 找到答案退出条件:容易理解,记住要用&&

写完递归退出条件,就要写 visited = true,表示当前的这个格子已经走过了。然后写下一层的路径,一般是一个循环里面是 dfs。下一层路径写完 visited = false 恢复这个格子未被访问的身份,dfs 函数也差不多要结束啦。

改正了 deadly signal 的错误,暴力使用DFS递归的结果是超时:
超时
这是因为 DFS 对于每一条路径都会走到目的地,才会尝试下一条路。对于 DFS 来说,要找最短的路径,需要每个答案都彻头彻尾算一遍,才能确定最终答案。

BFS 从一开始就是尝试所有情况,所以只要找到第一个达到的那个点,那就是最短的路径,可以直接返回了,其他情况都可以省略了。

所以。
求最短,BFS更高效。
找一个答案,DFS 更省时间。

更省时间的BFS

BFS 的标准使用方法是 while,具体来说一个一个坐标塞进队列,就是层次遍历树的套路。本题是从左上角开始,右下角结束,正好符合一圈一圈扩散开来,每一层不管走的哪条路,只记录一个层数。如果此路不通,就返回 -1,如果能走下去,就返回层数。

这是思考问题的另一种方式吧,思维上 DFS 更直观,BFS 并没有直接记录路径长度这个信息,BFS 的路径长度是全局的,全部路径共享层数这个路径长度。

完成
BFS 因为只走一遍,直接把 grid 覆盖了也没关系,也不需要额外开空间存储 visited 了。先把坐标【row,col】压入队列,用 1 压住原来的数字,标志此路不通了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值