持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情
题目链接:1302. 层数最深叶子节点的和
题目描述
给你一棵二叉树的根节点 root
,请你返回 层数最深的叶子节点的和 。
提示:
- 树中节点数目在范围 之间。
示例 1:
输入: root = [1,2,3,4,5,null,6,7,null,null,null,null,8]
输出: 15
示例 2:
输入: root = [6,7,8,2,7,1,3,9,null,1,4,null,null,null,5]
输出: 19
整理题意
题目给定一颗二叉树,要求返回这颗二叉树的 层数最深的叶子节点值的总和 。
解题思路分析
遇到树的题目和图一样,是需要遍历的,此时考虑 深度 和 广度 两种搜索方式。
深度优先搜索
采用 DFS
深度优先搜索的方式,我们记录遍历到的最大层数 m
,当遍历到层数为 m
的节点时累加节点值。
广度优先搜索
采用 BFS
广度优先搜索的方式,我们只需层序遍历这颗二叉树即可,输出最后一层的节点值总和即可。
具体实现
深度优先搜索
- 对根节点进行
DFS
深度优先搜索,同时需要传入当前层数作为参数; - 使用全局变量记录二叉树的最大深度
m
和最大深度节点值的总和ans
; - 当遇到比当前记录的最大深度
m
还要大的节点时,更新最大深度m
,以及清空ans
之前所记录的值,从新记录下当前节点值。 - 如果遍历到于最大深度相等的节点,将其节点值累加在
ans
上即可; - 最后输出
ans
即可。
广度优先搜索
- 从根节点进行层序遍历;
- 不断记录每层的节点值总和;
- 输出最后一层节点值总和即可。
复杂度分析
- 时间复杂度:深度和广度优先搜索的时间复杂度都为 ,其中
n
是二叉树的节点数,深度和广度优先搜索都需要遍历每个节点一次。 - 空间复杂度:深度和广度优先搜索的空间复杂度都为 ,其中
n
是二叉树的节点数。深度优先搜索的空间复杂度取决于递归调用栈的深度,为二叉树的深度,最坏情况下二叉树的深度是 。广度优先搜索的空间复杂度主要取决于队列空间,队列中的节点个数不超过n
个。
代码实现
深度优先搜索
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
int m, ans;
void dfs(TreeNode* root, int deep){
// 维护最大值 m 和答案 ans
if(deep > m){
ans = 0;
m = deep;
}
if(deep == m) ans += root->val;
if(root->left) dfs(root->left, deep + 1);
if(root->right) dfs(root->right, deep + 1);
}
public:
int deepestLeavesSum(TreeNode* root) {
// 初始化最大值 m 为 0,ans 为 0
m = 0, ans = 0;
dfs(root, 0);
return ans;
}
};
广度优先搜索
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int deepestLeavesSum(TreeNode* root) {
if(root == nullptr) return 0;
// ans 记录每层节点值总和
int ans = 0;
queue<TreeNode*> que;
while(que.size()) que.pop();
// 从 root 开始层序遍历
que.push(root);
while(que.size()){
// 初始化每层节点值总和为 0
ans = 0;
int n = que.size();
for(int i = 0; i < n; i++){
TreeNode* now = que.front();
que.pop();
ans += now->val;
if(now->left) que.push(now->left);
if(now->right) que.push(now->right);
}
}
return ans;
}
};
总结
- 对于图和树的题目,通常需要进行遍历操作,遍历操作往往分为深度和广度两种形式。根据题目需求不同,采用对应遍历方式即可,对于本题来说,采用广度优先搜索的层序遍历更为符合题意。
- 测试结果:
对比二者在时间和空间复杂度上的差异实际上是并不大的,因为执行时网络的波动,会有所影响执行用时和内存,所以根据二者的执行用时和内存消耗进行对比是相差不大的。
结束语
成功从来没有捷径,任何梦想的实现都无法一蹴而就,每一阶段的抵达都离不开一步一个脚印的积累。停止为懒惰找借口,向着梦想勇敢前进。你未来的模样,就藏在现在的努力里。新的一天,加油!