题目难度: 中等
今天继续更新剑指 offer 系列, 这道题挺经典的, 这里提供递归和迭代两种方案供大家参考
老样子晚上 6 点 45 分准时更新公众号 每日精选算法题, 大家记得关注哦~ 另外在公众号里回复 offer 就能看到剑指 offer 系列当前连载的所有文章了
题目描述
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
- 节点总数 <= 10000
题目样例
示例
输入
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
输出
[
[5,4,11,2],
[5,8,4,5]
]
题目思考
- 如何用递归思路来解决? 需要保存哪些信息?
- 可以用前几天的 BFS 解决吗?
解决方案
方案 1
思路
- 首先考虑递归思路
- 这道题很适合用 DFS 来做, 因为在遍历的过程中可以保存路径中的节点, 以及当前和之类的信息
- 最后到叶子节点时只需要判断当前和是否等于目标, 是的话将路径加入结果中即可
- 递归出口自然就是当前节点是叶子节点了
- 如果不是叶子节点的话, 就递归调用非空的子节点, 将其值加入和中, 节点本身加入路径中即可
- 特别注意的是, 由于题目没有说节点值非负, 所以必须老老实实走到叶子节点才知道和是否等于目标. 不然如果节点值都是非负数的话, 就可以在当前和大于目标时直接返回了, 之后的和只可能更大, 肯定不满足条件
复杂度
- 时间复杂度
O(N)
- 每个节点只需要遍历一次
- 空间复杂度
O(N^2)
- 递归的栈的消耗是 N, 然后每个递归调用里面又要分配 N 个节点的路径
代码
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
if not root:
return []
res = []
def dfs(node, path, cur):
if cur == sum and not node.left and not node.right:
# 当前是叶子节点, 且和正好等于目标, 将路径加入结果中
res.append(path)
if node.left:
# 递归遍历非空左子节点
dfs(node.left, path + [node.left.val], cur + node.left.val)
if node.right:
# 递归遍历非空右子节点
dfs(node.right, path + [node.right.val], cur + node.right.val)
# 注意初始的路径以及和
dfs(root, [root.val], root.val)
return res
方案 2
思路
- 如果限制只能用迭代的话, 就不能用 DFS 了
- BFS 就是迭代, 但回忆之前的几种 BFS 方案 (
剑指 Offer 32
), 都只是存了节点本身, 我们如何把路径以及路径和关联起来呢? - 做法也很简单, 既然需要存额外信息, 我们就把队列的内容改造一下, 存成
(节点, 路径, 当前和)
三元组, 然后添加子节点的时候附带上对应路径以及当前和 - 这样如果当前节点是叶子节点的话, 只需要比较当前和与目标即可
复杂度
- 时间复杂度
O(N)
- 每个节点只需要遍历一次
- 空间复杂度
O(N^2)
- 队列需要存 N 个三元组, 每个元组中的路径又包含 N 个节点
代码
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
if not root:
return []
# 初始化根节点/路径/当前和
q = [(root, [root.val], root.val)]
res = []
for t in q:
node, path, sm = t
if not node.left and not node.right and sm == sum:
# 当前是叶子节点, 且和正好等于目标, 将路径加入结果中
res.append(path)
if node.left:
# 将非空左子节点/路径/当前和加入队列
q.append(
(node.left, path + [node.left.val], sm + node.left.val))
if node.right:
# 将非空右子节点/路径/当前和加入队列
q.append(
(node.right, path + [node.right.val], sm + node.right.val))
return res
大家可以在下面这些地方找到我~😊
我的公众号: 每日精选算法题, 欢迎大家扫码关注~😊