LeetCode 513.找树左下角的值

LeetCode 513.找树左下角的值

1、题目

题目链接:513. 找树左下角的值
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。

示例 1:
image.png

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

示例 2:
image.png

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

提示:

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

2、深度优先搜索(递归)

思路

这道题要在二叉树的 最后一行 找到 最左边的值
如果使用递归法,如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。所以要找深度最大的叶子节点。
那么如何找最左边的呢?可以使用前序遍历(当然中序,后序都可以,因为本题没有中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。
我们使用 maxDepth 用来记录最大深度,result 记录最大深度最左节点的数值。
在写递归时,我们要先明确递归三部曲:

  1. 确定递归函数的参数和返回值

参数必须有要遍历的树的根节点,depth 用来记录当前深度,maxDepth 用来记录最大深度,result 记录最大深度最左节点的数值。 这里就不需要返回值了,所以递归函数的返回类型为 void
代码如下:

void traversal(TreeNode* root, int depth, int& maxDepth, int& result)
  1. 确定终止条件

当遇到叶子节点的时候,就需要统计一下最大的深度了,所以需要遇到叶子节点来更新最大深度。
代码如下:

// 如果当前节点是叶子节点
if (root->left == nullptr && root->right == nullptr) {// 如果当前深度大于最大深度if (depth > maxDepth) {// 更新最大深度maxDepth = depth;// 更新结果值为当前节点的值result = root->val;}return;
}
  1. 确定单层递归的逻辑

在找最大深度的时候,递归的过程中依然要使用回溯。
代码如下:

// 如果左子节点存在
if (root->left) {// 深度加1depth++;// 递归遍历左子树traversal(root->left, depth, maxDepth, result);// 回溯,深度减1depth--;
}
// 如果右子节点存在
if (root->right) {// 深度加1depth++;// 递归遍历右子树traversal(root->right, depth, maxDepth, result);// 回溯,深度减1depth--;
}

代码

#include <iostream>
#include <climits>using namespace std;//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:void traversal(TreeNode* root, int depth, int& maxDepth, int& result) {// 如果当前节点是叶子节点if (root->left == nullptr && root->right == nullptr) {// 如果当前深度大于最大深度if (depth > maxDepth) {// 更新最大深度maxDepth = depth;// 更新结果值为当前节点的值result = root->val;}return;}// 如果左子节点存在if (root->left) {// 深度加1depth++;// 递归遍历左子树traversal(root->left, depth, maxDepth, result);// 回溯,深度减1depth--;}// 如果右子节点存在if (root->right) {// 深度加1depth++;// 递归遍历右子树traversal(root->right, depth, maxDepth, result);// 回溯,深度减1depth--;}return;}int findBottomLeftValue(TreeNode* root) {if (root == nullptr) {return 0;}// 记录最大深度int maxDepth = INT_MIN;// 记录最大深度最左节点的数值int result = 0;traversal(root, 0, maxDepth, result);return result;}
};int main() {Solution s;TreeNode* root = new TreeNode(3);root->left = new TreeNode(9);root->right = new TreeNode(20);root->right->left = new TreeNode(15);root->right->right = new TreeNode(7);cout << s.findBottomLeftValue(root) << endl;return 0;
}

复杂度分析

  • 时间复杂度: O(n),其中 n 是二叉树的节点数目。需要遍历 n 个节点。
  • 空间复杂度: O(n)。递归栈需要占用 O(n) 的空间。

3、深度优先搜索(递归精简版)

思路

在回溯的地方可以进行精简,在调用traversal函数时,depth加1,在递归结束时再减1,以确保在递归的不同层次上深度值是正确的。
代码如下:
traversal(root->right, depth + 1, maxDepth, result);

代码

class Solution {
public:void traversal(TreeNode* root, int depth, int& maxDepth, int& result) {// 如果当前节点是叶子节点if (root->left == nullptr && root->right == nullptr) {// 如果当前深度大于最大深度if (depth > maxDepth) {// 更新最大深度maxDepth = depth;// 更新结果值为当前节点的值result = root->val;}return;}// 如果左子节点存在if (root->left) {// 递归遍历左子树,这里隐藏了回溯操作,在调用traversal函数时,depth加1,在递归结束时再减1traversal(root->left, depth + 1, maxDepth, result);}// 如果右子节点存在if (root->right) {// 递归遍历右子树,这里隐藏了回溯操作,在调用traversal函数时,depth加1,在递归结束时再减1traversal(root->right, depth + 1, maxDepth, result);}return;}int findBottomLeftValue(TreeNode* root) {if (root == nullptr) {return 0;}// 记录最大深度int maxDepth = INT_MIN;// 记录最大深度最左节点的数值int result = 0;traversal(root, 0, maxDepth, result);return result;}
};

复杂度分析

  • 时间复杂度: O(n),其中 n 是二叉树的节点数目。需要遍历 n 个节点。
  • 空间复杂度: O(n)。递归栈需要占用 O(n) 的空间。

4、广度优先搜索(正向层序遍历)

思路

使用广度优先搜索遍历每一层的节点。遍历到最后一行的第一个结点就是要找的结点。

代码

class Solution {
public:int findBottomLeftValue(TreeNode* root) {// 如果根节点为空,返回0if (root == nullptr) {return 0;}// 创建一个队列用于层序遍历queue<TreeNode*> que;// 记录结果int result = 0;// 将根节点入队que.push(root);// 当队列不为空时,进行循环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)
  • 空间复杂度: O(n)

5、广度优先搜索(逆向层序遍历)

思路

使用广度优先搜索遍历每一层的节点。在遍历一个节点时,需要先把它的非空右子节点放入队列,然后再把它的非空左子节点放入队列,这样才能保证从右到左遍历每一层的节点。广度优先搜索所遍历的最后一个节点的值就是最底层最左边节点的值。

代码

class Solution {
public:int findBottomLeftValue(TreeNode* root) {// 如果根节点为空,返回0if (root == nullptr) {return 0;}// 创建一个队列用于层序遍历queue<TreeNode*> que;// 记录结果int result = 0;// 将根节点入队que.push(root);// 当队列不为空时,进行循环while (!que.empty()) {// 获取队首节点TreeNode* node = que.front();que.pop();// 如果该节点有右子节点,将右子节点入队if (node->right) {que.push(node->right);}// 如果该节点有右子节点,将右子节点入队if (node->left) {que.push(node->left);}// 更新结果为当前节点的值result = node->val;}return result;}
};

复杂度分析

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

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

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

相关文章

用字符串初始化的指针

一. 简介 前一篇文章简单学习了数组与指针的区别&#xff0c;文章如下&#xff1a; C语言中数组与指针的区别-CSDN博客 本文学习一下 初始化为 字符串的 指针。防止使用过程中出现问题。 二. 初始化指针来指向字符串 初始化指针来指向字符串&#xff0c;例如如下代码就是…

SpringBoot 具体是做什么的?

Spring Boot是一个用于构建独立的、生产级别的、基于Spring框架的应用程序的开源框架。它的目标是简化Spring应用程序的开发和部署过程&#xff0c;通过提供一种快速、便捷的方式来创建Spring应用程序&#xff0c;同时保持Spring的灵活性和强大特性。 1. 简化Spring应用程序开…

信安标委发布16项网络安全国家标准:8项为旧标准替代,8项标准为新发布

1. 背景 根据2024年4月25日国家市场监督管理总局、国家标准化管理委员会发布的中华人民共和国国家标准公告&#xff08;2024年第6号&#xff09;&#xff0c;全国网络安全标准化技术委员会归口的16项国家标准正式发布。 2. 标准清单 本次国家标准涵盖了信息技术安全评估准则、…

AScript纯本地离线文字识别插件

目的 AScript是一款可以模拟鼠标和键盘操作的自动化工具。它可以帮助用户自动完成一些重复的、繁琐的任务&#xff0c;节省大量人工操作的时间。但按键精灵是不包含图色功能&#xff0c;无法识别屏幕上的图像&#xff0c;根据图像的变化自动执行相应的操作。本篇文章主要讲解下…

苹果M4芯片:推动AI时代的革新力量

随着科技的飞速发展&#xff0c;苹果公司一直以其创新精神引领着行业潮流。其中&#xff0c;M4芯片的推出无疑是苹果在人工智能领域迈出的重要一步。这款专为机器学习和AI计算而设计的芯片&#xff0c;不仅在新款iPad Pro等消费电子产品上亮相&#xff0c;更是预示着苹果即将开…

数据库的使用基础-SQL语句

一、在MYSQL中&#xff0c;创建数据库&#xff0c;语法如下&#xff1a; CREATE DATABASE [IF NOT EXISTS] <数据库名> [[DEFAULT] CHARACTER SET <字符集名>] [[DEFAULT] COLLATE <校对规则名>];[ ]中的内容是可选的。语法说明如下&#xff1a; <数据库…

Mybatis入门之在基于Springboot的框架下拿到MySQL中数据

介绍 Java技术操作数据库 MyBatis是一款优秀的持久层框架 用于简化JDBC的开发 优秀的持久层框架 我们要基于Springboot整合Mybatis 实操 学习 基于Mybatis是如何操作数据库的 通过MyBatis书写SQL语句 SQL语句执行完毕后 会将查询结果返回给Java程序 表中数据会自动封装…

​​​【收录 Hello 算法】5.1 栈

目录 5.1 栈 5.1.1 栈的常用操作 5.1.2 栈的实现 1. 基于链表的实现 2. 基于数组的实现 5.1.3 两种实现对比 5.1.4 栈的典型应用 5.1 栈 栈&#xff08;stack&#xff09;是一种遵循先入后出逻辑的线性数据结构。 我们可以将栈类比为桌面上的一摞盘子…

Java面试——MyBatis

优质博文&#xff1a;IT-BLOG-CN 一、MyBatis 与 JDBC 的区别 【1】JDBC 是 Java 提供操作数据库的 API&#xff1b;MyBatis 是一个持久层 ORM 框架&#xff0c;底层是对 JDBC 的封装。 【2】使用 JDBC 需要连接数据库&#xff0c;注册驱动和数据库信息工作量大&#xff0c;每…

HTTP协议介绍

文章目录 http协议http协议格式GET请求POST请求http客户端实现 http协议 http协议是应用层协议&#xff0c;一般建立在tcp协议的基础之上&#xff08;当然你的实现非要基于udp也是可以的&#xff09;&#xff0c;也就是说http协议的数据收发是通过tcp协议的。 http协议也分为h…

Kivy UI界面

一、版本介绍 Ubuntu&#xff1a;18.04.6 LTS Conda&#xff1a;4.5.12 Python&#xff1a;3.6.15 Kivy&#xff1a;2.0.0 二、安装Kivy # 更新系统包列表 sudo apt-get update# 安装Kivy的依赖项 sudo apt-get install -y python-pip libsdl2-dev libsdl2-image-dev li…

定时任务执行 报错command not found 解决方案

目录 写在前面所需知识 问题复现解决方式方法1. 使用绝对路径的命令&#xff1a;方法2. 重新加载环境变量&#xff1a;成功解决截图 原理 写在前面 定时任务脚本出现command not found报错&#xff0c;解决方案。 所需知识 定时任务shell脚本环境变量 问题复现 编写了一个…

Neo4j 之安装和 CQL 基本命令学习

正常使用结构化的查询语言 SQL&#xff08;Structured Query Language&#xff09;较多一些&#xff0c;但是像 Neo4j 这种非结构化的图形数据库来说&#xff0c;就不得不学习下 CQL&#xff08;Cypher Query Language&#xff09;语言了。如果你之前学过 《离散数学》或《图论…

开源高性能的分布式时序数据库:Lindb

Lindb&#xff1a;为大数据时代量身打造的高性能时序数据库&#xff0c;让海量数据存储与实时分析触手可及。- 精选真开源&#xff0c;释放新价值。 概览 Lindb 是一款开源的分布式时序数据库&#xff0c;它以其高性能和可伸缩性在海量数据存储及快速查询计算方面展现出独特的…

Vue 中动态与静态处理 Element UI/Element Plus 组件禁用状态样式

目录 一、静态样式修改 - 使用 ::v-deep 穿透组件样式二、选择器的优先级和匹配顺序三、动态添加样式 - 使用 Vue 实例属性&#xff08;非推荐&#xff09;四、区别总结五、应用场景总结 本文主要探讨在 Vue.js 项目中&#xff0c;特别是搭配 Element UI 或 Element Plus 组件库…

将要上市的自动驾驶新书《自动驾驶系统开发》中摘录各章片段 4

第十三章 车联网 数字化设备正变得越来越普遍并且相互联系。这些设备向数字生态系统智能部分的演进创造了迄今为止尚未解决安全问题的新颖应用。一个特定的例子是车辆&#xff0c;随着车辆从简单的交通方式发展到具有新的感知和通讯功能的智能实体&#xff0c;就成为智能城市的…

Leecode438:找到字符串中所有字母异位词

做这道题的过程中遇到了很多问题&#xff0c;但其实都是自己不够仔细导致的。这道题的思想归根结底就是维护一个滑动窗口&#xff0c;然后在滑动的过程中不断维护不断判断&#xff0c;直到移到最后端然后返回一个维护好的list列表。

调试代码问题汇总

1.最常见的就是数据库密码不对。根据调试视频将你的数据库密码设置正确&#xff0c;数据库密码是数字的优先直接连如果不成功可以加个双引号或者单引号。 提示&#xff1a;java.sql.SQLException: Access denied for user rootlocalhost (using password: YES) 2.原本配置好的…

Three.js基础练习——渲染一个立方体

1.学习内容参考了 three.js入门教程--零基础也能学会_threejs菜鸟教程-CSDN博客 本章内容包含渲染立方体&#xff0c;并配合ui工具食用~ 2.效果图 import * as THREE from three import * as dat from dat.gui import { OrbitControls } from three/addons/controls/OrbitC…

Istio中的全局限流方案

Istio中的全局限流方案 在k8s网格&#xff08;istio&#xff09;环境中&#xff0c; 可以通过创建Envfoyfilter的方式来配置限流。 在istio官方文档中&#xff0c;提供了两种限流方式&#xff1a; 本地限流全局限流 本地限流的细节这里不再赘述, 主要讲解全局限流的配置方式…