leetcode刷题笔记——深度优先搜索

leetcode刷题笔记——深度优先搜索

目前完成的深度优先搜索相关的leetcode算法题序号:
简单:257
中等:200, 417

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reconstruct-itinerary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

文章目录

    • leetcode刷题笔记——深度优先搜索
  • 算法理解
  • 一、257题:二叉树的所有路径
    • 1.题干
    • 2.思路
    • 3.代码
    • 4.总结
  • 二、200题:岛屿数量
    • 1.题干
    • 2.思路
    • 3.代码
    • 4.总结
  • 三、1631题:最小体力消耗路径
    • 1. 题干
    • 2. 解题思路
    • 3. 代码
  • 四、417题:太平洋大西洋水流问题
    • 1. 题干
    • 2. 解题思路
    • 3. 代码


算法理解

刚刚接触到深度优先搜索(depth-first searches,DFS),先以一个实际案例简单谈谈自己的看法。
最先使用深度优先算法,是在迷宫问题上,需要在给定起点和终点的一个10*10大小的迷宫(以0-1值矩阵等效)中寻找可能的路径。
深度优先算法对于该问题,核心是以栈为基础,利用先进先出的机制,在遇到“死胡同”之后,一步步退回到上一个有其他路径选择的位置,选择其他的路径进行下一步的迭代。
由此认识到了深度优先搜索,虽然不一定能够找到最优路径,但也是迷宫问题的一种非常接近实际情况的解法思路:可以模拟为一个人在迷宫中在每一个岔路口对每一种走法进行尝试,直到某一条路不通(则放弃这种走法)或者某一条路到达终点,DFS将这种思路以算法的方式进行实现。
与广度优先搜索的区别,核心在于:广度优先搜索是基于队列(先进先出)的机制,在每一个分叉路口,考虑每一种的可能性,从而产生各个分支加入到队列中,后续同步对当前队列中所有的可能性进行搜索,能够保证搜索到其中一条的最优路径。


提示:以下是深度优先搜索的刷题笔记

一、257题:二叉树的所有路径

二叉树是指每个节点至多有2个分支的树结构,包括满二叉树和完全二叉树等特殊结构,本题的对象是普通二叉树。

1.题干

给定一个二叉树,返回所有从根节点到叶子节点的路径。
给定的树结构是带有左右子节点的数据节点,原始数据为根节点。

2.思路

利用深度优先搜索方法的话,最便捷的办法是利用递归的方法,从根节点开始自每一个节点对该节点的每一种分支进行递归,直到各个叶子节点,返回该叶子节点对应的路径。

3.代码

class Solution:
    def binaryTreePaths(self, root: TreeNode) -> List[str]:
		paths = []
        def searchway(root,path):
            if root:	#迭代函数中的if和while如何选择,老毛病了,要注意
                path += str(root.val)	#对于每一次迭代来说,先将非空节点的值保存到path变量中
                if not root.left and not root.right:	#判断是否为叶子节点
                    paths.append(path)	#如果是叶子节点,将该节点对应的路径存储到paths结果列表中
                else:	#如果不是叶子节点,说明还有左子节点,或右子节点
                    path += "->"	#将结果中要求的字符串格式添加进变量
                    searchway(root.left,path)	#对左右子节点进行迭代,注意变量的存储,递归函数要多注意函数中变量如何定义,从而实现函数的迭代作用
                    searchway(root.right,path)
                    
        searchway(root,"")	#从根节点开始迭代
        return paths    

4.总结

1.算法实现时的思维灵活性
在解决实际问题的过程中,深度优先算法更多的是一种思想,应该植入到我们在寻求问题解决路径的思维方法库中,要避免生搬硬套。
我刚开始思考这个题时,总是收到迷宫问题的影响,想要硬搬栈来套用,但是遇到了一个在这里不适用的一个问题:这里树节点是类似链表的节点类型,不能向前位来寻址回退,所以不适合套用栈,以出栈的方式来回到前一个分支点。
看了别人的解法之后,发现没必要一定要用到那种数据结构,重要的是用对解决问题最便利的思想,最简单的算法实现手段来进行编码,这里就直接用迭代的实现方法,结合深度搜索思想,非常便捷的解决了问题。
切忌生搬硬套,从实际问题本身出发!!!

2.与广度优先的比较
这个题当然还可以使用广度优先算法进行解决,相比于深度优先算法的迭代写法,代码实现要麻烦一些。在迷宫问题中,我一直觉得是不是广度优先要比深度优先在各方面都优秀一些,但是从这一题可以发现,深度优先在代码实现上,结合递归之后,实现上更简单,代码理解起来也更容易一点。
查资料找到的两者对比:
1.深度优先搜索有递归和非递归两种实现方法,对于深度较小,递归效果明显时使用递归实现会更简单易懂;
2.深度优先搜索如果每一次向下的搜索不是保留各深度的全部节点,只保存当前迭代对应的各个节点(比如迷宫问题),则需要存储的节点数,近似为节点的深度值,占用的空间比较少,因此,在搜索深度很大的场合,使用深度优先搜索能够有效避免内存溢出的情况;(深度优先占内存小,广度优先占内存大)
3.深度优先搜索常用栈(先进后出)结构,广度优先搜索常用队列(先进先出)结构;
4.深度优先搜索有进栈、出栈操作,处理速度要低于广度优先搜索;

二、200题:岛屿数量

1.题干

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿

你可能感兴趣的:(数据结构与算法,算法,二叉树,python,dfs)