hello 大家好啊,我是Johngo!
今天在同学面试了百度的商业广告部门的时候,一面有一个题答得不太好,然后面试完就找我聊了聊。
但是这的确是一个比较经典的题目,今天下午就拿出来给大家看看。
是有关二叉树的路径总和的题目,不妨从 DFS 和 BFS 两方面进行看看
LeetCode113 路径总和II
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有从根节点到叶子节点路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
之前的112题目,计算的是整个路径有没有路径和为 targetSum 的路径,同样是从根结点到叶子结点。
这个题目比较麻烦的一点是需要将满足要求的路径记录下来。
下面分别用 DFS 和 BFS 来解决一下这个问题。
树结点定义
class TreeNode(object):
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
DFS深度遍历解决
二叉树的深度遍历中,由于在计算过程中需要保存当前计算时结点的信息(包括从根结点到当前结点的结点值之和以及从根结点到当前结点的路径list)。所以在进行递归遍历的时候,需要在这两方面做计算。
对 targetSum
的处理:递归过程中,在遍历下一个结点的时候,将当前结点值减去,直到遍历到叶子结点的时候,判断不断被减去的 targetSum
剩余值是否和叶子结点的值一致。如果一致,那么,记录该路径。如果不一致,放弃该路径。
看下图的一个说明
对路径的处理:递归过程中,不断记录路径,当遍历到叶子结点的时候,如果满足条件,则将该路径保存到最终的结果集中。
看代码:
def pathSum_dfs(self, root, targetSum):
if not root:
return
res = []
def dfs(root, target_sum, path, res_path):
"""
:param root: 当前根结点
:param target_sum: 当前目标值
:param path: 当前路径列表
:param res_path: 当前最终结果路径列表
:return:
"""
if not root:
return
if not root.left and not root.right and target_sum == root.val:
res_path.append(path + [root.val])
dfs(root.left, target_sum - root.val, path + [root.val], res_path)
dfs(root.right, target_sum - root.val, path + [root.val], res_path)
dfs(root, targetSum, [], res)
return res
重点就是在tagetSum
方面做了一些文章,仔细看看,其实就是一个先序遍历的过程。
BFS处理
BFS的处理思路是非常清晰的
关于 BFS 处理树结构是非常清楚的。
思路就是在层序遍历过程中,遍历到各自结点的时候,记录当前信息。
如下:
很清晰的说明了在遍历到不同的结点的时候,记录:
当前结点
根结点到当前结点路径和
根结点到当前结点路径list
看本题代码:
def pathSum_bfs(self, root, targetSum):
if not root:
return
res = collections.deque() # 保存最后结果list
queue = collections.deque()
queue.appendleft((root, root.val, [root.val])) # (结点,根到当前结点累加和,根到当前结点路径)
while(queue):
node, node_val, node_path = queue.pop()
if not node.left and not node.right and node_val == targetSum:
res.appendleft(node_path)
if node.left:
queue.appendleft((node.left, node_val+node.left.val, node_path+[node.left.val]))
if node.right:
queue.appendleft((node.right, node_val+node.right.val, node_path+[node.right.val]))
return list(res)