【C/C++】1302. 层数最深叶子节点的和

227 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情


题目链接:1302. 层数最深叶子节点的和

题目描述

给你一棵二叉树的根节点 root ,请你返回 层数最深的叶子节点的和 。

提示:

  • 树中节点数目在范围 [1,104][1, 10^4] 之间。
  • 1Node.val1001 \leqslant Node.val \leqslant 100

示例 1:

1483_ex1.png

输入: 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 广度优先搜索的方式,我们只需层序遍历这颗二叉树即可,输出最后一层的节点值总和即可。

具体实现

深度优先搜索

  1. 对根节点进行 DFS 深度优先搜索,同时需要传入当前层数作为参数;
  2. 使用全局变量记录二叉树的最大深度 m 和最大深度节点值的总和 ans
  3. 当遇到比当前记录的最大深度 m 还要大的节点时,更新最大深度 m,以及清空 ans 之前所记录的值,从新记录下当前节点值。
  4. 如果遍历到于最大深度相等的节点,将其节点值累加在 ans 上即可;
  5. 最后输出 ans 即可。

广度优先搜索

  1. 从根节点进行层序遍历;
  2. 不断记录每层的节点值总和;
  3. 输出最后一层节点值总和即可。

复杂度分析

  • 时间复杂度:深度和广度优先搜索的时间复杂度都为 O(n)O(n),其中 n 是二叉树的节点数,深度和广度优先搜索都需要遍历每个节点一次。
  • 空间复杂度:深度和广度优先搜索的空间复杂度都为 O(n)O(n),其中 n 是二叉树的节点数。深度优先搜索的空间复杂度取决于递归调用栈的深度,为二叉树的深度,最坏情况下二叉树的深度是 O(n)O(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;
    }
};

总结

  • 对于图和树的题目,通常需要进行遍历操作,遍历操作往往分为深度和广度两种形式。根据题目需求不同,采用对应遍历方式即可,对于本题来说,采用广度优先搜索的层序遍历更为符合题意。
  • 测试结果:

1302 层数最深叶子节点的和.png

1302 层数最深叶子节点的和 BFS.png 对比二者在时间和空间复杂度上的差异实际上是并不大的,因为执行时网络的波动,会有所影响执行用时和内存,所以根据二者的执行用时和内存消耗进行对比是相差不大的。

结束语

成功从来没有捷径,任何梦想的实现都无法一蹴而就,每一阶段的抵达都离不开一步一个脚印的积累。停止为懒惰找借口,向着梦想勇敢前进。你未来的模样,就藏在现在的努力里。新的一天,加油!