输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
分析:我们可以先从最简单的情况开始考虑,最简单的情况就是二叉树只有一个根节点,判断根节点的值与期望值是否相同就ok了。二叉树稍微复杂一点就是根节点还有左右子节点,这时候的过程就要多一步,仍旧是先判断根节点的值与期望值,如果相等或者期望值更小,则不必继续向下判断,如果期望值更大,那么可以向下继续判断,此时的期望值变成了“期望值-根节点的值”,用新的期望值分别与左右子节点的值进行比较,因为左右子节点已经是叶节点,符合路径的定义,因此如果节点的值与新的期望值相等,就得到了答案,如果不相等,问题无解。现在推广到普通的二叉树,与上面的分析相同,就是一个不断更新期望值并与节点值比较的过程,这个过程是重复的,可以利用递归完成,下面来看一下具体代码。
首先定义二叉树
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
寻找路径的代码
class Solution:
#打印出二叉树中结点值的和为输入整数的所有路径。
def FindPath(self, root, expectNumber):
ans=[]#所有路径的集合
if root==None:
return ans
def iterpath(root,expectNumber,dir=[]):
if expectNumber>root.val:
dir.append(root.val)#dir保存当前路径(不一定是符合要求的路径)
#分别在左右子树中寻找并更新期望值
if root.left!=None:
iterpath(root.left,expectNumber-root.val,dir)
if root.right!=None:
iterpath(root.right,expectNumber-root.val,dir)
elif expectNumber==root.val:
dir.append(root.val)
if root.right==None and root.left==None:#如果节点的值与期望值相同,则判断节点是否为叶子结点,如果是叶子结点则是符合条件的路径
tmp=dir[:]
ans.append(tmp)
else:
dir.append(0)
dir.pop()#!!!!!!!!!!!!!
iterpath(root,expectNumber)
return ans
代码中有一个地方要注意,dir.pop()这一句,我已经用感叹号标识出来,这是必须要有的。原因是这样的,我们先来看一下这句什么时候会被执行,在判断节点值与期望值的大小关系时,有三种情况,如果期望值大于节点值,则会递归调用函数继续判断;如果是相等,则判断节点是否为叶子节点;如果期望值小于节点值,也有相应的操作。因此,在当前路径结束或者已经发现当前路径不符合要求时,会直接执行pop操作,pop操作的目的就是让dir从当前节点重新回到其父亲节点,然后去判断另一棵子树。如果不执行pop操作,dir会保存经过的所有的节点,就不是一条正常的路径了。因此,当期望值小于节点值时,dir仍旧会执行一次append操作,就是因为后面会把这个值pop出去。