leetcode题解513:找树左下角的值(递归中的回溯处理)!

article/2025/7/28 11:40:44

一、题目内容:

题目要求找到一个二叉树的最底层最左边节点的值。具体来说,我们需要从根节点开始遍历二叉

树,找到最深的那层中的最左边的节点,并返回该节点的值。因为要先找到最底层左侧的值,所以我们选择遍历顺序一定是左侧先遍历,右侧后遍历。

我们需要声明depth、MaxDepth和result,depth记录当前深度、MaxDepth记录最大深度深度、result记录深度最大值,但在遍历中我么会思考到,如果遍历到某一叶子节点,但是当前结点深度并不是最大的,那么递归会回退到其父结点,这时就需要将深度回溯,这一过程如何实现呢,我们会在代码中体现。

二、题目分析

输入和输出

  • 输入:二叉树的根节点 root

    • 二叉树的每个节点是一个 TreeNode 对象,包含:

      • val:节点的值(整数)。

      • left:指向左子节点的指针。

      • right:指向右子节点的指针。

  • 输出:最底层最左边节点的值(整数)。

深度优先遍历函数 trevesal

  • 参数

    • root:当前节点。

    • depth:当前节点的深度。

  • 逻辑

    • 如果当前节点是叶子节点(即没有左子节点和右子节点)则:

      • 如果当前深度 depth 大于 maxDepth,则更新 maxDepthresult

    • 如果当前节点有左子节点则:

      • 递归调用 trevesal,深度加1。

    • 如果当前节点有右子节点则:

      • 递归调用 trevesal,深度加1。

    • 回溯:在递归调用结束后,深度减1,以恢复到当前节点的深度。

三、代码解答

1.C++代码

class Solution {
public:int maxDepth = INT_MIN;  // 用于记录当前找到的最深的叶子节点的深度int result;              // 用于存储最底层最左边节点的值// 定义递归函数,用于深度优先搜索void trevesal(TreeNode *root, int depth) {// 如果当前节点是叶子节点(没有左子节点和右子节点)if (root->left == NULL && root->right == NULL) {// 如果当前深度大于已知的最大深度if (depth > maxDepth) {result = root->val;  // 更新结果值为当前节点的值maxDepth = depth;    // 更新最大深度为当前深度}}// 如果当前节点有左子节点if (root->left) {depth++;  // 深度加1,进入下一层trevesal(root->left, depth);  // 递归遍历左子节点depth--;  // 回溯,恢复到当前节点的深度}// 如果当前节点有右子节点if (root->right) {depth++;  // 深度加1,进入下一层trevesal(root->right, depth);  // 递归遍历右子节点depth--;  // 回溯,恢复到当前节点的深度}}// 主函数,用于调用递归函数并返回结果int findBottomLeftValue(TreeNode* root) {trevesal(root, 0);  // 从根节点开始,深度为0return result;      // 返回最底层最左边节点的值}
};

详细注释

1. 成员变量
int maxDepth = INT_MIN;  // 初始化为最小整数,表示当前找到的最深的叶子节点的深度
int result;              // 用于存储最底层最左边节点的值
  • maxDepth:记录当前找到的最深的叶子节点的深度,初始值为 INT_MIN,确保任何叶子节点的深度都会比它大。

  • result:存储最底层最左边节点的值,初始值未定义,会在递归过程中被赋值。

2. 递归函数 trevesal
void trevesal(TreeNode *root, int depth) {// 如果当前节点是叶子节点(没有左子节点和右子节点)if (root->left == NULL && root->right == NULL) {// 如果当前深度大于已知的最大深度if (depth > maxDepth) {result = root->val;  // 更新结果值为当前节点的值maxDepth = depth;    // 更新最大深度为当前深度}}// 如果当前节点有左子节点if (root->left) {depth++;  // 深度加1,进入下一层trevesal(root->left, depth);  // 递归遍历左子节点depth--;  // 回溯,恢复到当前节点的深度}// 如果当前节点有右子节点if (root->right) {depth++;  // 深度加1,进入下一层trevesal(root->right, depth);  // 递归遍历右子节点depth--;  // 回溯,恢复到当前节点的深度}
}
  • 叶子节点检查

    • 如果当前节点没有左子节点和右子节点,说明它是一个叶子节点。

    • 如果当前叶子节点的深度大于已知的最大深度 maxDepth,则更新 resultmaxDepth

  • 递归遍历左子节点

    • 如果当前节点有左子节点,深度加1,递归调用 trevesal 遍历左子节点。

    • 递归返回后,深度减1,恢复到当前节点的深度。这是回溯的关键步骤,确保每次递归返回后,深度值正确。

  • 递归遍历右子节点

    • 如果当前节点有右子节点,深度加1,递归调用 trevesal 遍历右子节点。

    • 递归返回后,深度减1,恢复到当前节点的深度。同样,这是回溯的关键步骤。

3. 主函数 findBottomLeftValue
int findBottomLeftValue(TreeNode* root) {trevesal(root, 0);  // 从根节点开始,深度为0return result;      // 返回最底层最左边节点的值
}
  • 调用递归函数

    • 从根节点开始,初始深度为0,调用 trevesal 函数。

  • 返回结果

    • 递归完成后,返回 result,即最底层最左边节点的值。

回溯和递归的详细解释

递归
  • 递归是一种函数调用自身的方法,用于解决复杂问题。在本题中,递归用于遍历二叉树的每个节点。

  • 每次递归调用时,深度 depth 增加1,表示进入下一层。

  • 递归调用的终止条件是当前节点是叶子节点(没有左子节点和右子节点)。

回溯
  • 回溯是一种在递归调用返回后恢复状态的机制。

  • 在本题中,每次递归调用返回后,深度 depth 减1,恢复到当前节点的深度。

  • 这样可以确保每次递归返回后,深度值正确,不会影响后续的递归调用。

示例

假设二叉树如下:

    1/ \2   3/   / \
4   5   6
遍历过程
  1. 从根节点 1 开始,深度为0。

    • 调用 trevesal(1, 0)

  2. 遍历左子节点 2,深度为1。

    • 调用 trevesal(2, 1)

  3. 遍历左子节点 4,深度为2。

    • 调用 trevesal(4, 2)

    • 4 是叶子节点,且深度大于 maxDepth,更新 maxDepth=2result=4

    • 返回到节点 2,深度减1,恢复为1。

  4. 返回到根节点 1,深度减1,恢复为0。

  5. 遍历右子节点 3,深度为1。

    • 调用 trevesal(3, 1)

  6. 遍历左子节点 5,深度为2。

    • 调用 trevesal(5, 2)

    • 5 是叶子节点,但深度等于 maxDepth,不更新。

    • 返回到节点 3,深度减1,恢复为1。

  7. 遍历右子节点 6,深度为2。

    • 调用 trevesal(6, 2)

    • 6 是叶子节点,但深度等于 maxDepth,不更新。

    • 返回到节点 3,深度减1,恢复为1。

  8. 返回到根节点 1,深度减1,恢复为0。

最终,result=4,即最底层最左边的节点值。

总结

通过递归和回溯,代码能够有效地找到二叉树最底层最左边的节点值。递归用于遍历二叉树,回溯用于恢复状态,确保每次递归返回后,深度值正确。


http://www.hkcw.cn/article/MqSIxEuWsX.shtml

相关文章

React项目在ios和安卓端要做一个渐变色背景,用css不支持,可使用react-native-linear-gradient

以上有个模块是灰色逐渐到白的背景色过渡 如果是css,以下代码就直接搞定 background: linear-gradient(180deg, #F6F6F6 0%, #FFF 100%);但是在RN中不支持这种写法,那应该写呢? 1.引入react-native-linear-gradient插件,我使用的是…

Nginx进阶篇(Nginx静态资源概述、Nginx静态资源配置指令、Nginx静态资源优化配置、Nginx静态资源压缩)

文章目录 1. Nginx静态资源概述2. Nginx静态资源配置指令2.1 listen指令2.2 server_name指令2.2.1 精确匹配2.2.2 补充知识:hosts文件2.2.3 通配符匹配2.2.4 正则表达式匹配2.2.5 匹配的执行顺序 2.3 location指令2.3.1 uri以指定模式开始(/)…

SAP 生产订单收货数量超额报错问题研究

工单收货接口报错有点奇怪,明明是生产订单收货,报错消息中却一直说采购订单收货。 其实之前有发现,只是知道原因(收货数量超过工单总数量),没太关注描述问题,这次好好研究下。 首先检查消息号&…

【连接器专题】SD卡座规格书审查需要审哪些方面?

在审查SD卡座规格书时,我们需要考虑哪些方面? 首先在拿到一份SD卡座的详细规格书时,一般供应商给到的规格书中包括了一些基础信息、产品图纸信息、技术参数信息,同时有些供应商会给出产品可靠性测试报告。因此我们会从这几个要素去看规格书。 基础信息 基础信息一般会给变更…

sward V1.1.4版本发布,支持文档审批及文档导出

sward是一款国产开源企业级知识管理工具,包含知识库管理、文档管理、文档协作、文档分享等模块,支持普通文档、markdown等格式,产品简洁易用、开源免费。本周sward发布V1.1.4版本,增加了文档审批和文档导出为word的功能&#xff0…

谷云科技发布业内首份 Oracle OSB 迁移到 iPaaS 技术白皮书

随着企业数字化转型的加速推进,从传统企业服务总线ESB向现代化集成平台iPaaS迁移已成为行业发展的必然趋势。Oracle Service Bus(OSB)在ESB产品市场中长期以来一直占据着较高的市场份额。然而,许多用户由于担心技术迁移的复杂性和…

特伦斯 S75 电钢琴:重塑音乐感知,臻享艺术之境

在音乐文化蓬勃发展的当下,电钢琴已成为音乐爱好者探索旋律世界的热门之选。在这方充满无限可能的音乐领域,特伦斯 S75 电钢琴以其超凡的设计与卓越的性能,打破传统电钢琴的局限,为用户带来无与伦比的音乐体验,宛如一颗…

立控信息智能装备柜:科技赋能军队装备管理现代化

在军事装备管理领域,高效、安全、智能化的存储解决方案至关重要。传统的人工管理模式不仅效率低下,还容易因人为疏忽导致装备丢失或管理混乱。​LKONE智能装备柜凭借先进的物联网技术、生物识别安全系统和智能管理功能,为军队提供了一套高效、…

【freertos-kernel】queue(接收)

文章目录 xQueueReceivexQueueReceiveFromISRxQueuePeekxQueuePeekFromISR xQueueReceive 从队列中接收一个数据项。 和发送数据的过程有点类似,不逐行解释代码了。 vTaskPlaceOnEventList把当前任务放进队列的等待链表的同时也会把当前任务从就绪列表移除&#x…

Clish中xml文件配置的使用方法

1&#xff0c;引入 之前介绍了klish的源码如何安装和使用&#xff0c;本次介绍一下klish的xml配置文件是如何使用的&#xff0c;介绍其中的<COMMAND>/<PARAM>/<PTYPE>等基础配置&#xff0c;方便以后查看。 2&#xff0c;clish中xml文件的基本语法 1&#…

Compose仿微信底部导航栏NavigationBar :底部导航控制滑动并移动

文章目录 1、准备工作1.1 参考1.2 依赖添加&#xff1a;1.3 主要控件NavigationBarHorizontalPager、VerticalPager 2、功能描述&#xff1a;3、实现过程3.1 创建一个数据类3.2 创建一个list变量3.3 具体实现3.3.1 创建共享的Pager状态3.3.2 将页面索引与页面标题同步3.3.3 创建…

由反汇编代码确定结构体的完整声明

C程序中遇到下面的代码 typedef struct {int left;a_struct a[CNT];int right; } b_struct;void test( int i, b_struct *bp) {int nbp->leftbp->right;a_struct *ap&bp->a[i];ap->x[ap->idx]n; } 下面是test函数的反汇编代码 结合C程序中的代码与test函数…

生成式人工智能:重塑社会的双刃剑与人类文明的抉择

普罗米修斯之火与文明的抉择 当古希腊神话中的普罗米修斯盗取天火赠予人间时&#xff0c;人类文明开启了从蒙昧走向理性的征程。今天&#xff0c;生成式人工智能&#xff08;GenAI&#xff09;正以类似的方式重塑人类认知的边界——它既是照亮未来的火炬&#xff0c;也是可能灼…

TestHubo V1.1.0版本发布,新增用例评审功能,确保测试用例质量,提升测试用例覆盖率

TestHubo是一款开源免费的测试管理工具&#xff0c;提供一站式测试解决方案&#xff0c;涵盖功能测试、接口测试、性能测试以及 Web 和 App 测试等多个维度。本周TestHubo V1.1.0版本发布&#xff0c;新增用例评审功能。 1、版本更新日志 新增 ➢ 用例评审&#xff1a;通过评…

正点原子Z15I ZYNQ 开发板发布!板载PCIe2.0、SPFx2、MIPI CSI等接口,资料丰富!

正点原子Z15I ZYNQ 开发板发布&#xff01;板载PCIe2.0、SPFx2、MIPI CSI等接口&#xff0c;资料丰富&#xff01; 正点原子Z15I ZYNQ开发板&#xff0c;核心板全工业级设计&#xff0c;主控芯片的型号是XC7Z015CLG485-2I。开发板由核心板&#xff0b;底板组成&#xff0c;外设…

易路 iBuilder:解构企业 AI 落地困境,重构智能体时代生产力范式

一、从大模型到智能体的产业跃迁 2024 年堪称中国人工智能产业的 "战略拐点" 之年。当 DeepSeek R1 模型以 "技术 价格" 双重普惠模式掀起行业震荡时&#xff0c;各企业纷纷意识到&#xff0c;大模型的真正价值不在于技术炫技&#xff0c;而在于成为企业…

DiTAR: Diffusion Transformer Autoregressive Modeling for Speech Generation

kaiming 文章的codepaper abstract LLM 预测连续embedding&#xff0c;直接接DiT。和kaiming-Autoregressive Image Generation without Vector Quantization的文章思路一样。- LLM是casual attention&#xff0c;和diffusion 一起训练&#xff0c;相比于full attention会有性…

AC220V整流滤波电路Multisim仿真

一、仿真电路&#xff1a; 二、遇到的问题 1、仿真运行保险丝会熔断&#xff0c;然后输出电压不对。 解&#xff1a;这里可能是整流桥的模型不对&#xff0c;更换了一个新的模型&#xff0c;仿真就可以正常运行了。 2、整流桥的电流方向和问题 正半周&#xff1a; 负半周&a…

【后端高阶面经:架构篇】50、数据存储架构:如何改善系统的数据存储能力?

一、数据存储架构设计核心原则 (一)分层存储架构:让数据各得其所 根据数据访问频率和价值,将数据划分为热、温、冷三层,匹配不同存储介质,实现性能与成本的平衡。 热数据层:访问频率>100次/秒。采用Redis集群存储高频访问数据(如用户登录态、实时交易数据),配合…

安卓逆向篇Smail 语法反编译签名重打包Activity 周期Hook 模块

常见安卓逆向工具及环境&#xff1a; 1 、安卓模拟器&#xff08;最好 root 的真机&#xff09; 2 、 Magisk&XP&LSP 框架 HOOK 环境 安装参考&#xff1a; https://blog.csdn.net/danran550/article/details/132256027 3 、 Jadx-Gui 反编译 Java 代码查看…