257 二叉树的所有路径(dfs)

1. 问题描述:

给定一个二叉树,返回所有从根节点到叶子节点的路径。

说明: 叶子节点是指没有子节点的节点。

示例:

输入:

  1
 /   \
2     3
 \
  5

输出: ["1->2->5", "1->3"]

解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-paths

2. 思路分析:

① 对于二叉树的所有操作都是可以使用递归来解决的,对于这道题目来说主要是需要一个数据结构来记录中间的路径中的节点,一开始想到的是使用list列表来进行记录(我们是可以在递归调用之前将当前的路径节点添加到列表中),在递归的出口也就是递归方法的一开始就判断出当前的节点是否是叶节点,假如是叶节点说明一条路径就已经形成了,这个时候将路径加入到结果集中

② 对于使用列表(引用类型变量)来记录中间结果需要注意一个回溯的问题,比如在递归到当前路径1-2-5的时候list列表会记录"1->2->5"这个路径,而我们需要尝试其他的路径的时候这个时候就需要将列表中之前删除的路径节点删除掉,这个时候就需要考虑在递归的哪一个地方进行删除,实际上对于这种问题画出具体的一颗二叉树就知道删除节点的时候(回溯)处理的地方在哪里了:

257 二叉树的所有路径(dfs)_第1张图片257 二叉树的所有路径(dfs)_第2张图片

像上面这一棵二叉树,我们是在self.dfs(root.left, rec, res)调用完之后删除呢还是在self.dfs(root.right, rec, res)调用之后进行删除呢?比如dfs方法调用到2这个节点,来到下面的一大块的地方也就是self.dfs(root.left, rec, res)代码的前面,然后继续调用左子树发现2的左子树为空这个时候遇到root is None 所以会退回到2这个节点调用的位置,也就是返回到这一句代码self.dfs(root.left, rec, res)的位置,这个时候我们是不能够删除2这个节点的,也就是在左子树调用完之后不能够进行回溯的,因为还需要尝试下面的4这个节点,所以回溯的位置是不能够在self.dfs(root.left, rec, res)后面进行的,因为这个时候会把2这个节点删除掉,我们是需要在调用完2的右子树之后进行回溯的,也就是self.dfs(root.right, rec, res)这句代码后面进行删除节点

其实也好理解,因为尝试完当前节点左右子树的路径之后才可以对当前的节点进行删除,自己根据具体的二叉树也是很好理解的

257 二叉树的所有路径(dfs)_第3张图片257 二叉树的所有路径(dfs)_第4张图片

③ 除了使用str类型的列表之外,还可以使用str类型的变量进行记录中间的路径,str类型与List类型不一样的是List类型有点像引用类型当调用的时候改变了之后退回到上一层这个变量也是改变了的,str类型的变量退回到上一层之后则不会改变所以使用这个来记录非常方便不用进行回溯也可以

3. 代码如下:

List[str]记录:

from typing import List


class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:

    def dfs(self, root: TreeNode, rec: List[str], res: List[str]):
        if root is None: return
        if root.left is None and root.right is None:
            # 需要将当前的叶子节点加入到路径中
            rec.append(str(root.val))
            # 叶子节点
            newlist = list()
            # 拷贝全部元素到新列表中
            newlist = rec[:]
            # 删除叶子节点
            rec.pop()
            res.append("->".join(newlist))
            return res

        rec.append(str(root.val))
        self.dfs(root.left, rec, res)
        self.dfs(root.right, rec, res)
        rec.pop()

    def binaryTreePaths(self, root: TreeNode) -> List[str]:
        if root is None: return []
        res = list()
        self.dfs(root, list(), res)
        return res


if __name__ == '__main__':
    root = TreeNode(1)
    l = TreeNode(2)
    r = TreeNode(3)
    lr = TreeNode(5)
    root.left = l
    root.right = r
    l.right = lr
    print(Solution().binaryTreePaths(root))

str类型变量记录:

from typing import List


class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    # 使用str类型的变量来记录中间过程中生成的路径节点(比列表要方便一点)
    def dfs(self, root: TreeNode, rec: str, paths: List[str]):
        if not root: return
        # 叶子节点
        if not root.left and not root.right:
            rec += str(root.val)
            paths.append(rec)
            return
        rec += str(root.val) + "->"
        self.dfs(root.left, rec, paths)
        self.dfs(root.right, rec, paths)

    def binaryTreePaths(self, root: TreeNode) -> List[str]:
        paths = []
        self.dfs(root, "", paths)
        return paths

 

你可能感兴趣的:(递归与搜索,领扣)