题目介绍
描述:
给你一棵二叉树,请你返回层数最深的叶子节点的和。
示例:
输入:root = [1,2,3,4,5,null,6,7,null,null,null,null,8]
输出:15
提示:
树中节点数目在 1 到 10^4 之间。
每个节点的值在 1 到 100 之间。
解题思路:
递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果。
写树相关的算法,简单说就是,先搞清楚当前 root 节点该做什么,然后根据函数定义递归调用子节点,递归调用会让孩子节点做相同的事情。
二叉树题目的一个难点在于如何通过题目的要求思考出每一个节点需要做什么
二叉树解题策略
一 递归 二 队列 + 迭代 (层次遍历) 三 栈 + 迭代 (非递归遍历) 四 其它
三种基本的遍历方式,都可以用递归来实现。写递归算法的时候,需要注意递归退出条件以及递归操作的表达。
分解两部分,第一拿到最深节点和对应的值,然后求和。
自己的解法实现
def deepestLeavesSum3(self, root):
res, level = 0, 0
maxDepth = -1
stack = [root]
while stack:
for _ in range(len(stack)):
node = stack.pop(0)
if level > maxDepth:
maxDepth = level
res = node.val
elif level == maxDepth:
res += node.val
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
level += 1
return res
网上比较优秀的解法
解法一
方法一:深度优先搜索 我们可以使用深度优先搜索的方法解决这个问题。
我们从根节点开始进行搜索,在搜索的同时记录当前节点的深度 dep。我们维护两个全局变量 maxdep 和 total,其中 maxdep 表示搜索到的节点的最大深度,total 表示搜索到的深度等于 maxdep 的节点的权值之和。
当我们搜索到一个新的节点 x 时,会有以下三种情况:
节点 x 的深度 dep 小于 maxdep,那么我们可以忽略节点 x,继续进行搜索;
节点 x 的深度 dep 等于 maxdep,那么我们将节点 x 的权值添加到 total 中;
节点 x 的深度 dep 大于 maxdep,此时我们找到了一个深度更大的节点,因此需要将 maxdep 置为 dep,并将 total 置为节点 x 的权值。
在深度优先搜索结束之后,深度最大的叶子节点的权值之和即存储在 total 中。
def __init__(self):
self.maxdep = -1
self.total = 0
def deepestLeavesSum(self, root):
def dfs(node, dep):
if not node: return
if dep > self.maxdep:
self.maxdep, self.total = dep, node.val
elif dep == self.maxdep:
self.total += node.val
dfs(node.left, dep + 1)
dfs(node.right, dep + 1)
dfs(root, 0)
return self.total
解法二
广度优先搜索
def deepestLeavesSum2(self, root):
from collections import deque
queue = deque([(root, 0)])
maxdep, total = -1, 0
while queue:
node, dep = queue.popleft()
if dep > maxdep:
maxdep, total = dep, node.val
elif dep == maxdep:
total += node.val
if node.left:
queue.append((node.left, dep + 1))
if node.right:
queue.append((node.right, dep + 1))
return total
解法三
每层结果初始化为0,每层迭代时计入结果。最深层即为最新迭代的结果
相关知识总结和思考
相关知识:
BFS:广度/宽度优先。其实就是从上到下,先把每一层遍历完之后再遍历一下一层。
可以使用Queue的数据结构。我们将root节点初始化进队列,通过消耗尾部,插入头部的方式来完成BFS。
二叉搜索树(BST)的特性:
- 若它的左子树不为空,则所有左子树上的值均小于其根节点的值
- 若它的右子树不为空,则所有右子树上的值均大于其根节点的值
- 它的左右子树也分别为二叉搜索树
递归与迭代的区别
递归:重复调用函数自身实现循环称为递归; 迭代:利用变量的原值推出新值称为迭代,或者说迭代是函数内某段代码实现循环;