最近刷LeetCode里树的专题时,有一系列跟路径有关的题目,比如:路径总和(看是否存在一条路径的总和为某一数值、返回所有总和为某一数值的路径)、二叉树的所有路径、二叉树的最大(最小)深度。这些都与路径有关即深度优先遍历,套路也差不多,稍微改动一下即可。
一、【LeetCode 112】路径总和
1.题目描述
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
2.思路
(1)首先定义一个深度优先遍历的辅助函数DFS(self, root, result, path)
来获取该二叉树的所有路径:
- 定义出口:若当前节点的左节点和右节点均不存在(说明走到叶子节点)并且路径值之和等于给定的数值,则直接将该路径添加到result里面;
- 接下来就是递归,若当前节点的左节点不为空,则将左节点添加至已有路径中
self.DFS(root.left, result, path + [root.left.val])
;同理,若右节点不为空,也将右节点添加至已有路径中self.DFS(root.right, result, path + [root.right.val])
(2)回到主函数:
- 首先判空,若树不存在直接返回False即可;
- 接着调用DFS函数,得到result:判断若result不为空,说明里面包含了路径也即表明存在这样一条路径等于给定值,返回True;否则直接返回False。
3.代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def hasPathSum(self, root: TreeNode, sum: int) -> bool:
result = []
if not root:
return False
self.sum = sum
self.DFS(root, result, [root.val])
if result:
return True
return False
def DFS(self, root, result, path):
if not root.left and not root.right and sum(path) == self.sum:
result.append(path)
if root.left:
self.DFS(root.left, result, path + [root.left.val])
if root.right:
self.DFS(root.right, result, path + [root.right.val])
二、【LeetCode 113】路径总和II
1.题目描述
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
返回:
[
[5,4,11,2],
[5,8,4,5]
]
2.思路
跟112题的思路几乎一模一样,只不过112题是看是否存在这样一条路径,本题是返回所有满足要求的路径,DFS函数里不用改动,直接在主函数里返回result即可。
3.代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
result = []
if not root:
return result
self.sum = sum
self.DFS(root, result, [root.val])
return result
def DFS(self, root, result, path):
if not root.left and not root.right and sum(path) == self.sum:
result.append(path)
if root.left:
self.DFS(root.left, result, path + [root.left.val])
if root.right:
self.DFS(root.right, result, path + [root.right.val])
三、【LeetCode 257】二叉树的所有路径
1.题目描述
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入:
1
/ \
2 3
\
5
输出: [“1->2->5”, “1->3”]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
2.思路
思路与上面两题大同小异,还少了一个确定路径总和的步骤,辅助函数DFS可不变,只不过该题的输出有点变化,类似于链表,要用到join()函数将数组self.result里的元素先变成字符串,再用’->'连接起来输出即可。
3.代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
self.result = []
if not root:
return []
self.DFS(root, [root.val])
self.result = ['->'.join([str(i) for i in item]) for item in self.result]
return self.result
def DFS(self, root, path):
if not root.left and not root.right:
self.result.append(path)
if root.left:
self.DFS(root.left, path + [root.left.val])
if root.right:
self.DFS(root.right, path + [root.right.val])
四、【LeetCode 111】二叉树的最小深度
1.题目描述
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最小深度 2.
2.思路
最初的思路是按照257题那样把所有路径列出来,然后求出长度最小的路径即为最小深度,于是就有了下面的代码,这样看起来有点像暴力法,虽说没有超出时间限制,但是运行时间真的慢,所以参考了别人的题解之后,觉得有一种方法很赞,见第四部分。
3.代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:
return 0
result = []
self.DFS(root, result, [root.val])
res = []
for li in result:
res.append(len(li))
return min(res)
def DFS(self, root, result, path):
if not root.left and not root.right:
result.append(path)
if root.left:
self.DFS(root.left, result, path + [root.left.val])
if root.right:
self.DFS(root.right, result, path + [root.right.val])
4.优化后的代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:
return 0
if not root.left and not root.right:
return 1
if not root.left and root.right:
return self.minDepth(root.right) + 1
if root.left and not root.right:
return self.minDepth(root.left) + 1
else:
return min(self.minDepth(root.left), self.minDepth(root.right)) + 1
与第3部分的代码相比,这个就更清爽直接一些:
(1)若树不存在,就直接返回0;
(2)若只有根节点或者到叶子节点时就返回1;
(3)若当前节点的左子树不存在,右子树存在,则对右子树进行递归计算深度;
(4)若当前节点的左子树存在,右子树不存在,同理;
(5)左子树和右子树同时存在的时候,就取两者的最小值 + 1(加一是表示当前子树的父节点)
五、【LeetCode 104】二叉树的最大深度
1.题目描述
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
2.思路
和【二叉树的最小深度】思路一模一样,一个求最小值,一个求最大值。
3.代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:
return 0
if not root.left and not root.right:
return 1
if not root.left and root.right:
return self.maxDepth(root.right) + 1
if root.left and not root.right:
return self.maxDepth(root.left) + 1
else:
return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
六、【LeetCode 129】求根到叶子节点数字之和
1.题目描述
给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。
例如,从根到叶子节点路径 1->2->3 代表数字 123。
计算从根到叶子节点生成的所有数字之和。
说明: 叶子节点是指没有子节点的节点。
示例 1:
输入: [1,2,3]
1
/ \
2 3
输出: 25
解释:
从根到叶子节点路径 1->2 代表数字 12.
从根到叶子节点路径 1->3 代表数字 13.
因此,数字总和 = 12 + 13 = 25.
2.第一种代码
在遍历的节点的时候就将节点值转换为字符串连接,最后将得到的字符串转换为整型相加即可。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
self.res = 0
if not root:
return 0
self.DFS(root, '')
return self.res
def DFS(self, root, tmp):
if not root.left and not root.right:
self.res += int(tmp + str(root.val))
if root.left:
self.DFS(root.left, tmp + str(root.val))
if root.right:
self.DFS(root.right, tmp + str(root.val))
3.第二种代码
思路和前几题类似,用到了深度优先遍历辅助函数DFS,还是先得到所有的路径,然后处理这个存有所有路径的列表:先对每个路径中的每个元素的十分位,百分位或千分位进行转换,然后使用sum()函数求和即可得到一个连续的路径表示,最后将这些值相加即可。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
result = []
if not root:
return 0
self.DFS(root, result, [root.val])
values = []
for item in result:
res = [i *10**index for index,i in enumerate(item[::-1])]
value = sum(res)
values.append(value)
val = sum(values)
return val
def DFS(self, root, result, path):
if not root.left and not root.right:
result.append(path)
if root.left:
self.DFS(root.left, result, path + [root.left.val])
if root.right:
self.DFS(root.right, result, path + [root.right.val])
补充
a = [1, 2, 3, 4, 5]
a = [i *10**index for index, i in enumerate(a[::-1])
b = sum(a)
print(b)
输出:12345