129、求根节点到叶节点数字之和
给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。
每条从根节点到叶节点的路径都代表一个数字:
- 例如,从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123 。
计算从根节点到叶节点生成的 所有数字之和 。
叶节点 是指没有子节点的节点。
示例1:
输入:root = [1,2,3]
输出:25
解释:
从根到叶子节点路径 1->2 代表数字 12
从根到叶子节点路径 1->3 代表数字 13
因此,数字总和 = 12 + 13 = 25
示例2:
输入:root = [4,9,0,5,1]
输出:1026
解释:
从根到叶子节点路径 4->9->5 代表数字 495
从根到叶子节点路径 4->9->1 代表数字 491
从根到叶子节点路径 4->0 代表数字 40
因此,数字总和 = 495 + 491 + 40 = 1026
思路:
可以先求出二叉树所有路径,然后进行求和
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
def getPath(root):
if not root: return []
if not root.left and not root.right: return [root.val]
left = getPath(root.left)
right = getPath(root.right)
# 这里直接字符串拼接,后面转换成数字进行求和即可
return [f"{root.val}{item}" for item in left + right]
paths = getPath(root)
return sum(int(value) for value in paths)
改进:
由于上面的代码要不断的拼接字符串,产生大量的内存消耗,我们知道一个结点的所代表的的数字值应该是 父节点代表的数字值 * 10 + 当前结点的值,所以在递归的时候,传递父节点的值,这样就可以计算出每个节点的值
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
# 递归求该节点左右子树的数字和
def dfs(root, parentTotal):
if not root: return 0
# 计算当前结点所代表的的数字值
total = parentTotal * 10 + root.val
# 如果没有子节点,直接返回即可
if not root.left and not root.right:
return total
# 那么当前结点的数字和就是左右子节点的数字值之和
return dfs(root.left, total) + dfs(root.right, total)
return dfs(root, 0)
也可以使用迭代的方式进行实现,在层序遍历的基础上,我们可以给队列中传一个元组,包含当前节点以及父节点的数字和,那么当该节点没有子节点的时候,可以将数字和累加即可
class Solution:
def sumNumbers(self, root: TreeNode) -> int:
if not root: return 0
# 元组包含的是当前结点以及父节点代表的数字
queue = [(root, 0)]
ans = 0
while queue:
node, preSum = queue.pop(0)
# 计算出当前结点代表的数字
curSum = preSum * 10 + node.val
# 如果没有子节点,进行累加
if not node.left and not node.right:
ans += curSum
continue
if node.left:
queue.append((node.left, curSum))
if node.right:
queue.append((node.right, curSum))
return ans
508、出现次数最多的子树元素和
给你一个二叉树的根结点 root ,请返回出现次数最多的子树元素和。如果有多个元素出现的次数相同,返回所有出现次数最多的子树元素和(不限顺序)。
一个结点的 「子树元素和」 定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身)。
示例1:
输入: root = [5,2,-3]
输出: [2,-3,4]
示例2:
输入: root = [5,2,-5]
输出: [2]
思路:
递归计算节点的值,然后根据节点的值更新结果。
class Solution:
def __init__(self):
self.ans = []
self.cache = collections.defaultdict(int)
self.maxCount = 0
def update(self, val):
# 将值出现的次数缓存起来
if val in self.cache:
self.cache[val] += 1
else:
self.cache[val] = 1
count = self.cache[val]
# 如果count等于maxCount,那么说明出现次数相同的值,加入到结果中
if count == self.maxCount:
self.ans.append(val)
return
# 如果count大于maxCount,那么更新结果集
if count > self.maxCount:
self.ans = [val]
self.maxCount = count
def findFrequentTreeSum(self, root: TreeNode) -> List[int]:
def dfs(root):
if not root: return 0
left = dfs(root.left)
right = dfs(root.right)
# 节点的值等于当前结点值 + 左右节点的值
rootVal = root.val + left + right
# 更新结果
self.update(rootVal)
return rootVal
if not root: return []
dfs(root)
return self.ans
面试题0412求和路径
给定一棵二叉树,其中每个节点都含有一个整数数值(该值或正或负)。设计一个算法,打印节点数值总和等于某个给定值的所有路径的数量。注意,路径不一定非得从二叉树的根节点或叶节点开始或结束,但是其方向必须向下(只能从父节点指向子节点方向)。
示例1:
输入: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], sum = 22
输出: 3
解释:和为 22 的路径有:[5,4,11,2], [5,8,4,5], [4,11,7]
思路:
通过递归求路径和,如果当前结点等于目标值说明已找到一条路径
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> int:
def dfs(root, target):
if not root: return 0
path = 0
if root.val == target:
path += 1
# 左右子树满足目标值的路径树
left = dfs(root.left, target - root.val)
right = dfs(root.right, target - root.val)
return path + left + right
if not root: return 0
# 由于不限于根节点所以递归根节点,左右子节点
return dfs(root, sum) + self.pathSum(root.left, sum) + self.pathSum(root.right, sum)