LeetCode513. 找树左下角的值

news2024/11/15 8:44:54

513. 找树左下角的值

文章目录

      • [513. 找树左下角的值](https://leetcode.cn/problems/find-bottom-left-tree-value/)
        • 一、题目
        • 二、题解
          • 方法一:递归法(层序遍历,深度优先搜索)
            • **不足之处以及如何改进**
          • 方法二:迭代


一、题目

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

示例 1:

img

输入: root = [2,1,3]
输出: 1

示例 2:

img

输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7

提示:

  • 二叉树的节点个数的范围是 [1,104]
  • -231 <= Node.val <= 231 - 1

二、题解

方法一:递归法(层序遍历,深度优先搜索)

我们可以使用递归来进行深度优先搜索,将每一层的节点值按照层级存储在一个二维向量中,最后返回最底层最左边的节点值。

算法思路:

  1. 使用深度优先搜索(DFS)来遍历整个二叉树。
  2. 在遍历的过程中,我们需要记录每个节点所在的层级,然后将节点值存储在对应的层级中。
  3. 为了达到这个目的,我们可以使用一个二维向量 result,其中 result[i] 存储第 i 层的节点值。
  4. 我们定义一个辅助函数 find,接受三个参数:vec 用来存储节点值,node 当前处理的节点,depth 当前节点的深度。
  5. find 函数中,我们首先检查当前节点是否为空,如果是,则直接返回。
  6. 如果 depth 等于 vec 的大小,说明当前层级还没有被记录,因此需要在 vec 中添加一个新的空向量。
  7. 将当前节点值加入到 vec[depth] 中,然后递归处理左子树和右子树,将深度加一传递下去。
  8. 在主函数 findBottomLeftValue 中,我们首先创建一个空的二维向量 result
  9. 调用 find 函数来遍历二叉树并填充 result
  10. 返回 result 最底层最左边的节点值,即 result[result.size() - 1][0]

具体实现:

class Solution {
public:
    void find(vector<vector<int>>& vec, TreeNode* node, int depth) {
        if (node == nullptr) {
            return;
        }
        
        if (depth == vec.size()) {
            vec.push_back(vector<int>());
        }
        
        vec[depth].push_back(node->val);
        find(vec, node->left, depth + 1);
        find(vec, node->right, depth + 1);
    }
    
    int findBottomLeftValue(TreeNode* root) {
        vector<vector<int>> result;
        find(result, root, 0);
        return result[result.size() - 1][0];
    }
};

算法分析:

  • 时间复杂度:遍历整个二叉树的时间复杂度为 O(N),其中 N 是二叉树的节点数。在每个节点上,我们进行常数时间的判断、添加和递归操作。
  • 空间复杂度:递归函数的调用会占用栈空间,递归的深度最坏情况下为树的高度,所以空间复杂度为 O(H),其中 H 是二叉树的高度。在最坏情况下,二叉树可能退化为链表,高度为 N,此时空间复杂度为 O(N)。但在一般情况下,二叉树的高度平衡,空间复杂度会接近 O(logN)。
不足之处以及如何改进

上面这个算法在递归过程中对左子树和右子树都会调用 findLeftMostValue 函数,即使在左子树的递归中已经找到了最底层最左边节点,仍然会递归处理右子树。这会导致不必要的重复计算。

改进版算法通过在递归中记录已找到的最大深度 maxDepth,只在当前深度大于最大深度时才更新 resultmaxDepth。这样,如果我们在某一层已经找到了最底层最左边的节点,就不会再继续递归处理右子树,从而减少了不必要的递归操作。

改进版本

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        int depth = 0; // 记录当前节点的深度
        int result = 0; // 记录最底层最左边节点的值
        findLeftMostValue(root, 1, depth, result);
        return result;
    }
    
    void findLeftMostValue(TreeNode* node, int currentDepth, int& maxDepth, int& result) {
        if (!node) {
            return;
        }
        //这里进行了改良,当深度发生变化时result也发生变化,直到最底层
        if (currentDepth > maxDepth) {
            result = node->val;
            maxDepth = currentDepth;
        }
        
        findLeftMostValue(node->left, currentDepth + 1, maxDepth, result);
        findLeftMostValue(node->right, currentDepth + 1, maxDepth, result);
    }
};
方法二:迭代

算法思路:

我们也可以使用队列来进行广度优先搜索,逐层遍历二叉树。具体的算法思路如下:

  1. 我们首先创建一个空队列 que,用来存储待处理的节点。
  2. 如果根节点 root 不为空,我们将根节点入队列。
  3. 我们定义一个变量 result 来记录最底层最左边节点的值,初始值设为 0。
  4. 开始循环处理队列中的节点,直到队列为空。
  5. 在每一层遍历中,我们首先获取当前队列的大小 size,即当前层的节点个数。
  6. 然后,我们使用一个循环来处理当前层的所有节点:
    • 弹出队首节点 node,如果是当前层的第一个节点(即 i == 0),我们将其值赋给 result
    • 如果 node 的左子节点不为空,将左子节点入队列。
    • 如果 node 的右子节点不为空,将右子节点入队列。
  7. 当队列为空时,循环结束,此时 result 中存储的就是最底层最左边节点的值,我们将其返回。

具体实现:

/**
 * 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 findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        if (root) que.push(root);
        int result = 0;
        
        while (!que.empty()) {
            int size = que.size();
            
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                
                if (i == 0) {
                    result = node->val; // 记录最后一行第一个元素
                }
                
                if (node->left) {
                    que.push(node->left);
                }
                
                if (node->right) {
                    que.push(node->right);
                }
            }
        }
        
        return result;
    }
};

算法分析:

  • 时间复杂度:遍历整个二叉树的时间复杂度为 O(N),其中 N 是二叉树的节点数。在每个节点上,我们进行常数时间的判断、入队和出队操作。
  • 空间复杂度:队列 que 会占用额外的空间,其大小不会超过二叉树的宽度,因此空间复杂度为 O(W),其中 W 是二叉树的宽度,最坏情况下会达到 O(N)。在一般情况下,二叉树的宽度较小,空间复杂度会接近 O(1)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/833211.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年08月在线IDE流行度最新排名

点击查看最新在线IDE流行度最新排名&#xff08;每月更新&#xff09; 2023年08月在线IDE流行度最新排名 TOP 在线IDE排名是通过分析在线ide名称在谷歌上被搜索的频率而创建的 在线IDE被搜索的次数越多&#xff0c;人们就会认为它越受欢迎。原始数据来自谷歌Trends 如果您相…

三、文件与路径

1、隐藏文件与非隐藏文件 1.1、概念 (1)隐藏文件默认情况下看不到&#xff0c;需要进行相应设置才能看到。非隐藏文件默认情况下就能看到 1.2、Windows中的文件 (1)非隐藏文件设置为隐藏文件。选中文件&#xff0c;鼠标右键→属性&#xff0c;勾选隐藏。 (2)产看隐藏文件。…

资产盘点设备包括哪些

根据资产管理系统的卡账表和计算机设备管理系统的验证&#xff0c;固定资产的账卡完成一致&#xff1b;根据上级领导机构发布的资产盘点标示&#xff0c;固定资产。低价值易耗品进行标签贴绑&#xff0c;完成帐实一致&#xff0c;真实反映本行固定资产实物情况。   RFID固定…

RocketMQ 事务消息

事务消息是 RocketMQ 的高级特性之一 。这篇文章&#xff0c;笔者会从应用场景、功能原理、实战例子三个模块慢慢为你揭开事务消息的神秘面纱。 1 应用场景 举一个电商场景的例子&#xff1a;用户购物车结算时&#xff0c;系统会创建支付订单。 用户支付成功后支付订单的状态…

论测试猿如何优雅的甩锅

测试猿&#xff0c;经常被江湖人戏称为“背锅侠”。 这个称呼是怎么来的呢&#xff1f;我们来追溯一下根源。 当产品上线后&#xff0c;有 bug&#xff1a; “测试为什么没有测试发现这个问题&#xff1f;肯定是测试的责任&#xff01;” 当产品上线后&#xff0c;用户反馈…

Windows server上用nginx部署vue3项目

Windows server上用nginx部署vue3项目 一、报错信息三、总结 一、报错信息 这里&#xff0c;nginx给出以下错误信息&#xff1a; Windows&#xff1a;nginx: [error] CreateFile() “/logs/nginx.pid“ failed (2: The system&#xff09; 经分析&#xff0c;造成上述错误的本…

小研究 - 领域驱动设计DDD在IT企业内部网站开发中的运用(一)

在企业内部网站的建设过程中&#xff0c;网站后端最初采用传统的表模式的开发方式。这种方式极易导致站点的核心业务逻辑和业务规则分布在架构的各个层和对象中&#xff0c;这使得系统业务逻辑的复用性不高。为了解决这个问题&#xff0c;作者在后期的开发过程中引入了领域驱动…

ad+硬件每日学习十个知识点(18)23.7.29 (LDO原理、LDO的补偿引脚)

文章目录 1.LDO名字介绍2.LDO的应用范围3.LDO的原理4.LDO输出端和输入端的差值至少满足多少V&#xff1f;怎么计算的&#xff1f;5.输出的误差和输出电流&#x1f446;&#xff08;右下角图像&#xff09;6.LDO一般会有个引脚是做补偿之用&#xff0c;datasheet会说明一个器件的…

云原生全栈体系(二)

Kubernetes实战入门 第一章 Kubernetes基础概念 一、是什么 我们急需一个大规模容器编排系统kubernetes具有以下特性&#xff1a; 服务发现和负载均衡 Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器&#xff0c;如果进入容器的流量很大&#xff0c;Kubernetes 可以负…

2023华数杯数学建模竞赛选题建议

提示&#xff1a;DS C君认为的难度&#xff1a;C<B<A&#xff0c;开放度&#xff1a;B<A<C 。 A题&#xff1a;隔热材料的结构优化控制研究 A题是数模类赛事很常见的物理类赛题&#xff0c;需要学习不少相关知识。 其中第一问需要建立平纹织物整体热导率与单根纤…

知识区博主转型——兼做知识区和改造区博主!!!!!

想脱单的进来&#xff0c;一起交流如何能脱单&#xff01;&#xff01;&#xff01; 为什么——我太羡慕有对象的人了哭死&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 你是不是很羡慕别人怎么都有女朋友 别人家的女朋友怎么都那么好&#xff…

用户权限管理是保证企业图文档安全最有效的策略

企业拥有大量的图文档数据&#xff0c;涉及多个部门和员工&#xff0c;因此需要建立有效的用户权限管理策略&#xff0c;以保护图文档的安全。智橙平台将在线图文档管理与BOM系统的融合应用为企业提供了强大的权限管理功能&#xff0c;能够确保只有授权用户能够访问和编辑特定的…

【设计模式——学习笔记】23种设计模式——迭代器模式Iterator(原理讲解+应用场景介绍+案例介绍+Java代码实现)

文章目录 案例引入介绍基础介绍应用场景登场角色 案例实现案例一实现 案例二实现 迭代器模式在JDK源码中的应用总结文章说明 案例引入 编写程序展示一个学校院系结构: 需求是这样&#xff0c;要在一个页面中展示出学校的院系组成&#xff0c;一个学校有多个学院&#xff0c;一…

小白如何获取CNVD事件型原创漏洞证明?——记CNVD漏洞挖掘思路

引子: 相信许多人都想要被别人叫做大佬&#xff0c;漏洞挖掘当中肯定也不例外,所以在此之前让我们康康度娘对大佬的定义:形容一个人很巨表示对其顶礼膜拜的态度。在这种情况下&#xff0c; 国家信息安全漏洞共享平台(CNVD) 则为我们提供了一个成为大佬的平台, CNVD作为国内最具…

【javaSE】 实现图书管理系统

目录 整体思路 Book包 Book类 BookList类 user包 User类 NormalUser类 AdminUser管理员类 testmain包 opera包 IOPeration接口 普通用户 ExitOperation类 FindOperation类 BrrowOperation类 ReturnOperation类 管理员 AddOperation类 DelOperation类 ShowOp…

小白科普-通信网中核心网、城域网、接入网

通信网络的一个整体结构&#xff0c;大致包括&#xff1a;骨干网、核心网、城域网、接入网&#xff0c;其中接入网又分为无线接入和有线接入&#xff0c;以及承载网。 听起来很复杂&#xff0c;我们再分解来看看。 从最靠近用户端开始的是接入网。接入网&#xff0c;简单点来…

迁移学习(新人必看)

先说一下深度学习常见的问题&#xff1a; 1.数据集不够&#xff0c;通常用数据增强解决。 2.参数难以确定&#xff0c;训练时间长&#xff0c;这就需要用迁移学习来解决 什么叫迁移学习呢&#xff1a;比方说有一个对100w的自行车数据集&#xff0c;并用VGG模型训练好的网络&…

【前端】网页

1 网页的相关概念 1.1什么是网页 网站 &#xff1a;是网页的集合 网页 &#xff1a;通常是HTML格式的文件&#xff0c;通过浏览器来阅读 网页是构成网站的基本要素&#xff0c;它通常由图片、链接、文字、声音、视频等元素组成。通常我们看到的网页&#xff0c;常见以.htm或…

【人工智能】PyTorch安装

文章目录 前言一、环境版本二、开始安装CPU版本安装&#xff08;GPU版本在下面-可以直接跳过&#xff09;GPU版本安装CUDA 下载安装cudnn 下载安装 总结 前言 PyTorch是一种开源深度学习框架&#xff0c;它由Facebook AI Research&#xff08;FAIR&#xff09;团队开发并维护。…

计划管理与项目管理:有何区别?

简而言之&#xff0c;是的。尽管它们经常互换使用并对全局产生影响&#xff0c;但它们是完全不同的。 在本文中&#xff0c;我们将了解计划和项目管理之间的差异&#xff0c;提供每个示例&#xff0c;并向您展示如何使计划和项目管理工作更有效地实现您的业务目标。 计划管理与…