当前位置: 首页 > news >正文

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)

相关文章:

LeetCode 513.找树左下角的值

LeetCode 513.找树左下角的值 1、题目 题目链接&#xff1a;513. 找树左下角的值 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1示例 2: 输入: [1,2,3,4,null…...

redis分片java实践、redis哨兵机制实现、redis集群搭建

redis分片java实践 linux安装redishttps://mp.csdn.net/mp_blog/creation/editor/134864302复制redis.conf配置文件成redis1.conf、redis2.conf、redis3.conf 修改redis的端口信息和存pid文件的路径。存pid文件的路径只要不同就行了&#xff0c;没什么特别要求。 指定配置文件…...

2024年四千价位段最具统治力的投影仪,坚果N1S 4K: 4K+三色激光=下一代4K

更高的亮度与分辨率、更强的对比度、更广的色域、更低的价格&#xff0c;家用智能投影企业在性能和价格上加速内卷。作为该领域的龙头和“卷王之王”&#xff0c;坚果投影率先将激光投影仪的价格拉入万元内&#xff0c;近期其又祭出一把杀手锏——坚果N1S 4K。该产品是首款4000…...

MySQL8.3升级踩坑记录

之前用的mysql5.7&#xff0c;目前被省公司发现有漏洞&#xff0c;需要升级mysql8.3&#xff0c;无奈只好升级&#xff0c;记录下踩坑经过 1、安装完以后设置环境变量&#xff0c;网上操作一大堆&#xff0c;以便于方便使用client 2、双击client 登录&#xff0c;开启远程访问…...

你写的每条SQL都是全表扫描吗

你写的每条SQL都是全表扫描吗&#xff1f;如果是&#xff0c;那MySQL可太感谢你了&#xff0c;每一次SQL执行都是在给MySQL上压力、上对抗。MySQL有苦难言&#xff1a;你不知道索引吗&#xff1f;你写的SQL索引都失效了不知道吗&#xff1f;慢查询不懂啊&#xff1f;建那么多索…...

每日两题 / 24. 两两交换链表中的节点 25. K 个一组翻转链表(LeetCode热题100)

24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 定义三个指针&#xff0c;交换前先保存ntnt指针为next->next&#xff0c;cur和next两个节点&#xff0c;然后将pre->next指向next 若pre为空&#xff0c;说明当前交换的节点为头两个节点&#xff0c;…...

【Linux】模拟实现bash(简易版)

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…...

C++ | Leetcode C++题解之第67题二进制求和

题目&#xff1a; 题解&#xff1a; class Solution { public:string addBinary(string a, string b) {string ans;reverse(a.begin(), a.end());reverse(b.begin(), b.end());int n max(a.size(), b.size()), carry 0;for (size_t i 0; i < n; i) {carry i < a.siz…...

如何确保UDP文件传输工具有最低稳定的传输速度?

在当前日新月异的数字时代背景下&#xff0c;文件传输工具已经成为我们日常生活与工作中不可或缺的一部分&#xff0c;尤其针对那些频繁涉及即时数据交互与多媒体流通的场景。 UDP协议&#xff0c;以其突出的高速传输与低延迟特性&#xff0c;脱颖而出成为众多用户的首选。不过…...

力扣爆刷第133天之动态规划收尾(距离编辑与回文子串)

力扣爆刷第133天之动态规划收尾&#xff08;距离编辑与回文子串&#xff09; 文章目录 力扣爆刷第133天之动态规划收尾&#xff08;距离编辑与回文子串&#xff09;一、72. 编辑距离二、647. 回文子串三、516. 最长回文子序列 一、72. 编辑距离 题目链接&#xff1a;https://l…...

List集合中对asList的使用

List<String> sArrays.asList(“qwe”,”cvb”,”mnb”); List<String> s1s.subList(1,2); System.out.Pintln(“s”);//输出结果&#xff1a;[qwe,cvb,mnb] System.out.Pintln(“s1”);//输出结果&#xff1a;[cvb] s1.add(“123qwe”);//报错&#xff1a;java…...

软件测试所有测试方法

β测试_Beta测试 β测试&#xff0c;英文是Beta testing。又称Beta测试&#xff0c;用户验收测试&#xff08;UAT&#xff09;。 β测试是软件的多个用户在一个或多个用户的实际使用环境下进行的测试。开发者通常不在测试现场&#xff0c;Beta测试不能由程序员或测试员完成。 …...

linux 下 /usr/local的作用

在Linux系统中&#xff0c;/usr/local目录扮演着特定的角色&#xff0c;它是为用户自安装的软件提供一个标准位置。以下是/usr/local目录的主要用途和特点&#xff1a; 用户级程序目录&#xff1a;该目录用于存放用户自行编译安装的软件或者第三方应用程序&#xff0c;区别于操…...

【web网页制作】html+css旅游家乡河南开封主题网页制作(4页面)【附源码】

HTMLCSS家乡河南主题网页目录 &#x1f354;涉及知识&#x1f964;写在前面&#x1f367;一、网页主题&#x1f333;二、页面效果Page1 首页Page2 开封游玩Page 3 开封美食Page4 留言 &#x1f308; 三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书 &#x1f40b;四…...

MySQL用命令行导出数据库

问题&#xff1a; 交作业的时候要求交数据文件&#xff0c;因为用的MySQL数据库&#xff0c;就在想怎么用命令行导出数据库&#xff0c;在csdn上找了其他文章&#xff0c;使用MySQL的命令行用下面语句&#xff0c;结果发生报错 mysqldump -u 用户名 -p 数据库名 > 输出地址…...

uniapp video 层级覆盖

层级覆盖 cover-view组件 我这里做了个判断 监听全屏时隐藏按钮 根据项目需求自行更改...

SparkSQL概述

1.1. SparkSQL介绍 SparkSQL&#xff0c;就是Spark生态体系中的构建在SparkCore基础之上的一个基于SQL的计算模块。SparkSQL的前身不叫SparkSQL&#xff0c;而是叫做Shark。最开始的时候底层代码优化、SQL的解析、执行引擎等等完全基于Hive&#xff0c;总是Shark的执行速度要比…...

docker 和 docker-compose

Docker是一种开源的容器化平台&#xff0c;它可以帮助开发人员将应用程序及其所有依赖项打包到一个独立的、可移植的容器中。这意味着您可以在任何地方运行Docker容器&#xff0c;而不需要担心环境差异或依赖项的问题。 Docker Compose是Docker官方提供的一个工具&#xff0c;…...

微信小程序支付(完整版)-ThinkPHP/Uniapp

技术说明 1.前端&#xff1a;uniapp、vue3 2.接口&#xff1a;PHP8、ThinkPHP8、MySQL8.0 3.微信支付- PHP&#xff0c;官方示例文档 4.示例代码的模型及业务自己进行调整&#xff0c;不要一味的复制粘贴&#xff01;&#xff01;&#xff01; 流程说明 1.小程序调用接口…...

同时安装多个nodejs版本可切换使用,或者用nvm管理、切换nodejs版本(两个详细方法)

目录 一.使用nvm的方法&#xff1a; 1.卸载nodejs 2.前往官网下载nvm 3.安装nvm 4.查看安装是否完成 5.配置路径和淘宝镜像 6.查看和安装各个版本的nodejs 7.nvm的常用命令 二.不使用nvm&#xff0c;安装多个版本&#xff1a; 1.安装不同版本的nodejs 2.解压到你想放…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...