几道tree递归详解
深感递归之优雅与清晰,特将几道递归解答再次总结之!
112. Path Sum 路径总和
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22
,
5 / \ 4 8 / / \ 11 13 4 / \ \ 7 2 1
返回 true
, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2
。
分析:
对于终止条件的考虑:
如果是空树直接返回false。
如果当前结点为叶子:(或者这么考虑,如果当前节点只有根节点,那如果其值==sum则true,否则false!)
- 情况1:根节点的值==sum:说明至少找了一条路径。返回True
- 情况2: 根节点的值!= sum: 返回False
否则分别递归检查左右子树是否有满足条件的路径。
1 # Definition for a binary tree node.
2 # class TreeNode:
3 # def __init__(self, x):
4 # self.val = x
5 # self.left = None
6 # self.right = None
7
8 class Solution:
9 def hasPathSum(self, root: TreeNode, sum: int) -> bool:
10 if not root:return False
11 if not root.left and not root.right:
12 return root.val==sum
13 if self.hasPathSum(root.left, sum-root.val):
14 return True
15
16 if self.hasPathSum(root.right,sum-root.val):
17 return True
18 return False
113. Path Sum II 路径总和 II
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22
,
5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1
返回:
[ [5,4,11,2], [5,8,4,5] ]
分析:上一题的升级版。
对于终止条件的考虑:
如果是空树,返回空列表
如果当前结点为叶子:该判断了:(或者这么考虑:如果只有一个根节点,那我们是不是应该返回[[root]]?)
- 此叶子节点的值==sum: 则说明找到了一个结果,返回这个结果:注意结果是列表的列表
- 此叶子节点的值 !=sum: 说明此时非解。返回空列表。
找到以当前结点为根的左子树满足条件的所有路径:然后将该头节点分别填到路径中!
找到以当前结点为根的右子树满足条件的所有路径:然后将该头节点分别填到路径中!
1 class Solution:
2 def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
3 if not root: return []
4 res = []
5 if not root.left and not root.right:
6 if root.val==sum:
7 return [[root.val]]
8 else:
9 return []
10 leftpath = self.pathSum(root.left, sum-root.val)
11 for path in leftpath:
12 res.append([root.val]+path)
13 rightpath = self.pathSum(root.right, sum-root.val)
14 for path in rightpath:
15 res.append([root.val]+path)
16 return res
以上是我自己实现。和leetcode热评思路一样,不过其简写如下:
1 def pathSum(self, root, sum):
2 if not root:
3 return []
4 if not root.left and not root.right and sum == root.val:
5 return [[root.val]]
6 tmp = self.pathSum(root.left, sum-root.val) + self.pathSum(root.right, sum-root.val)
7 return [[root.val]+i for i in tmp]
437. Path Sum III 路径总和 III
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
示例:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 10 / \ 5 -3 / \ \ 3 2 11 / \ \ 3 -2 1 返回 3。和等于 8 的路径有: 1. 5 -> 3 2. 5 -> 2 -> 1 3. -3 -> 11
这道题虽然标为easy,但是递归逻辑还比较复杂。
1 # Definition for a binary tree node.
2 # class TreeNode:
3 # def __init__(self, x):
4 # self.val = x
5 # self.left = None
6 # self.right = None
7
8 class Solution:
9 # 在以node为根节点的二叉树中,寻找包含node的路径,和为sum
10 # 返回这样的路径个数
11 def findpath(self, root, sum):
12 if not root:return 0 # 没有要求最终要达到叶子节点,所以如果搜索到空的话,返回0
13 res = 0
14 if root.val==sum:
15 res+=1
16 res += self.findpath(root.left, sum-root.val)
17 res += self.findpath(root.right, sum-root.val)
18 return res
19
20 # 以root为根节点的二叉树中,寻找和为sum的路径,返回这样的路径个数
21 def pathSum(self, root: TreeNode, sum: int) -> int:
22 if not root:return 0
23 res = self.findpath(root, sum) # 包含这个节点,其和为sum
24 res += self.pathSum(root.left, sum) # 不包含此结点,且和为sum(左子树)
25 res += self.pathSum(root.right, sum) # 不包含此节点,且和为sum(右子树)
26 return res