原题链接:Binary Tree Paths
一道新题,我想了好久也不会。。。TnT
以下代码是在Leetcode官方论坛里看到的,非常好:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# @param {TreeNode} root
# @return {string[]}
def binaryTreePaths(self, root):
if not root:
return []
return [str(root.val) + '->' + path
for kid in (root.left, root.right) if kid
for path in self.binaryTreePaths(kid)] or [str(root.val)]
代码非常简短。
讲解如下:
首先判断root
是否为空,如果不存在这个root
(即 为空),则返回一个空的list。
然后采用递归的方法。第二个return
中的两个for
等价于嵌套,之所以不写在同一行是为了提高可读性。第一个for
循环表示在root
的左右子树中选择一个,并且不能是空的子树;然后,第二个for
就是在该子树中利用递归方法。
最后的or [str(root.val)]
是只有一个根节点的情况时(传入的树只有根节点时,或者在递归当中会出现这种情况),不需要显示'->'
,所以直接返回根节点的值。
我们现在来仔细地分析一下这个递归为什么是合理的:
第一眼看上去,最后一块代码
return [str(root.val) + '->' + path
for kid in (root.left, root.right) if kid
for path in self.binaryTreePaths(kid)] or [str(root.val)]
返回的只是其中一条"root-to-leaf path",并不是所有条"root-to-leaf path"。因为有一个
+ path
,后面的两个for
都是为这个path
服务的。
但是我们注意观察最后的or [str(root.val)]
,由于这道题要返回的是"root-to-leaf path",所以一定会走到叶节点才返回,那么叶节点的特点是什么呢?没有左子树与右子树。所以,在递归中一定会执行到最后的or [str(root.val)]
。最后的for
循环是for path in XXXX
,所以or [str(root.val)]
得到的字符串两边的(代表list的)框框也不用担心了。
如果还是不明白,参见以下代码以及对应的输出: