小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
二叉树根节点到叶子节点和为指定值的路径
问题描述
给定一个节点数为 n 的二叉树和一个值 sum ,请找出所有的根节点到叶子节点的节点值之和等于的路径,如果没有则返回空。
例如: 给出如下的二叉树,sum = 22。
返回:[ [5,4,11,2], [5,8,9] ]
分析问题
这道题比较简单,本质上就是搜索二叉树。对于二叉树的搜索,我们知道有深度优先搜索和广度优先搜索两种,所有这道题我们也可以有两种方式来求解。
深度优先搜索
找出所有的根节点到叶子节点的节点值之和等于的路径,我们可以枚举每一条根节点到叶子节点的路径,如果路径和恰好为目标和时,我们就找到了一条满足条件的路径。
class Solution:
def pathSum(self, root, target):
if not root:
return []
#存放所有的路径
ret = list()
#记录根节点到当前节点的路径和,防止重复计算
path = list()
def dfs(root, target):
#将该节点对于的value加入path中
path.append(root.val)
target -= root.val
#如果为叶子节点,并且路径和等于target,则把该路径加入res中
if not root.left and not root.right and target == 0:
ret.append(path[:])
#如果左孩子不为空,继续去搜索
if root.left:
dfs(root.left, target)
#如果右孩子不为空,继续去搜索
if root.right:
dfs(root.right, target)
#将该节点弹出
path.pop()
dfs(root, target)
return ret
广度优先搜索
我们也可以采用广度优先搜索的方式来求解。这里,我们使用一个哈希表来记录树中的每一个节点的父节点,再每一次找到一个满足条件的叶子节点时,我们就从该叶子节点出发,不断的向父节点迭代,即可还原出一条路径,使得从根节点到叶子节点的路径和等于目标值。
import collections
class Solution:
def pathSum(self, root, target):
#如果root为空,直接返回
if not root:
return []
ret = []
#用来保存父节点和子节点的关系
parent = {}
#根节点的父节点为None
parent[root]=None
#从该节点出发,一直寻找到根节点,还原出一条路径
def getPath(node):
tmp = []
while node:
tmp.append(node.val)
node = parent[node]
ret.append(tmp[::-1])
#建立一个队列,保存遍历到哪个节点,初始时,把根节点加入
node_que = collections.deque([root])
#记录从根节点走到某个节点时,累加的距离为多少,初始时为0
value_count_que = collections.deque([0])
while node_que:
#出队
node = node_que.popleft()
#将该节点的值进行累加
rec = value_count_que.popleft() + node.val
#如果是根节点,判断是否等于目标值,如果相等,则保存路径
if not node.left and not node.right:
if rec == target:
getPath(node)
else:
#如果左孩子存在,将节点加入node_que,将rec加入value_count_que
if node.left:
parent[node.left] = node
node_que.append(node.left)
value_count_que.append(rec)
#如果右孩子存在,将节点加入node_que,将rec加入value_count_que
if node.right:
parent[node.right] = node
node_que.append(node.right)
value_count_que.append(rec)
return ret