LeetCode513:找树最左下角的值(bfs+dfs)

文章目录

  • 一、 题目描述
  • 解法一:层序遍历 (BFS) - 最直观的解法
    • 核心思路
    • 代码实现
    • 优缺点分析
  • 解法二:递归 (DFS) - 更深度的思考
    • 核心思路
    • 代码实现
    • 优缺点分析
  • 四、 总结与对比

LeetCode 513 - 寻找树的最后一行的最左侧的值,【难度:中等;通过率:73.8%】,这道题是检验对两种核心遍历策略——广度优先搜索 (BFS) 和深度优先搜索 (DFS) 理解与运用的绝佳试金石

一、 题目描述

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

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

示例:

示例 1:
示例 1

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

示例 2:
示例 2

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

解法一:层序遍历 (BFS) - 最直观的解法

既然问题涉及到“层”和“行”,那么广度优先搜索 (BFS) 无疑是最自然、最直观的解题思路。我们只需要逐层遍历,并想办法记录下每一层的第一个节点即可

核心思路

  1. 使用队列进行标准的层序遍历
  2. while 循环中,我们知道每一次循环都将处理新的一层
  3. 在开始处理这一层的所有节点之前,队列的头部元素 (queue.peek()) 正是这一层的最左侧节点
  4. 我们用一个变量 resultNode 来不断更新这个“每层的最左侧节点”。当整个 while 循环结束时,resultNode 自然就指向了最后一层的最左侧节点

代码实现

class Solution {public int findBottomLeftValue(TreeNode root) {Queue<TreeNode> queue = new LinkedList<>(); // 也可自行选择其他高效实现queue.add(root);TreeNode resultNode = null; // 用于记录最终结果节点while (!queue.isEmpty()) {// 在处理本层节点前,队列的头部就是本层的最左侧节点// 用 resultNode 把它“暂存”起来resultNode = queue.peek();int levelSize = queue.size(); // 获取初始当前层的节点数量// 遍历并处理当前层的所有节点for (int i = 0; i < levelSize; i++) {TreeNode node = queue.poll();// 将下一层的节点(从左到右)加入队列if (node.left != null) {queue.add(node.left);}if (node.right != null) {queue.add(node.right);}}}// 循环结束后,resultNode 指向的就是最后一层的最左侧节点return resultNode.val;}
}

优缺点分析

  • 优点:思路与问题描述高度契合,代码逻辑清晰,易于理解
  • 缺点:需要使用队列,空间复杂度为 O(W),其中 W 是树的最大宽度。对于一个茂盛的树,空间开销较大

解法二:递归 (DFS) - 更深度的思考

我们也可以用深度优先搜索(DFS)来解决这个问题。这里的核心思想是:如果我们能记录下每个节点的深度,那么我们只需要找到拥有最大深度的、并且最靠左的那个节点即可

核心思路

  1. 定义两个全局变量:maxDepth 记录遍历过程中遇到的最大深度,resultVal 记录在最大深度下最左侧节点的值
  2. 进行一次深度优先搜索(递归)。为了确保找到的是“最左侧”的节点,我们采用先序遍历的顺序(根-左-右)
  3. 在遍历每个节点时,我们比较当前节点的深度 currentDepth 和已知的最大深度 maxDepth
  4. 如果 currentDepth > maxDepth,这意味着我们第一次到达了一个更深的层次。由于我们是先遍历左子树,所以当前这个节点一定是这个新深度下的最左侧节点。此时,我们更新 maxDepthresultVal
  5. 如果 currentDepth <= maxDepth,我们不做任何操作,因为我们已经在这个深度或更深的深度找到了最左侧的节点

代码实现

class Solution {int maxDepth = -1; // 记录已发现的最大深度int resultVal = 0;   // 记录最大深度下最左侧节点的值public int findBottomLeftValue(TreeNode root) {// 从根节点开始 DFS,初始深度为 0dfs(root, 0);return resultVal;}/*** dfs* @param node  当前节点* @param depth 当前节点的深度*/private void dfs(TreeNode node, int depth) {if (node == null) {return;}// 核心逻辑:判断是否发现了新的更深层// 因为我们是先序遍历(先左后右),所以第一次到达一个新深度时,// 当前节点必然是该深度的最左侧节点if (depth > maxDepth) {maxDepth = depth; // 更新最大深度resultVal = node.val; // 更新结果值}// 搜索左子树dfs(node.left, depth + 1);// 搜索右子树dfs(node.right, depth + 1);}
}

优缺点分析

  • 优点:空间复杂度仅为递归栈的深度 O(H),对于窄而深的树,空间效率优于 BFS
  • 缺点:思路相对 BFS 来说不那么直观,需要正确处理深度和值的更新逻辑

四、 总结与对比

解法一 (层序遍历 / BFS)解法二 (递归 / DFS)
核心思路逐层遍历,不断用每层的第一个节点覆盖结果,直到最后一层深度优先,利用遍历顺序和深度记录,找到第一个到达最大深度的节点
数据结构队列 (Queue)递归栈
时间复杂度O(N)O(N)
空间复杂度O(W) (树的最大宽度)O(H) (树的最大高度)
代码可读性高,与问题描述匹配中等,需要理解深度更新的逻辑
适用场景解决所有与“层”相关的问题,通用性强空间效率可能更高,尤其是在处理细长的树时

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

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

相关文章

把“评论”菜单从WordPress后台移除的3种方法

在WordPress后台移除“评论”菜单&#xff0c;可以通过以下几种方法实现。以下是详细步骤&#xff1a; 方法1&#xff1a;通过代码移除(推荐) 将以下代码添加到主题的functions.php文件中(或使用CodeSnippets插件)&#xff1a; // 移除后台左侧菜单的“评论” add_action(ad…

大语言模型 LLM 通过 Excel 知识库 增强日志分析,根因分析能力的技术方案(4):只要过一遍LLM的简约版本

文章大纲 只要过一遍LLM的简约版本 1 设计原理(一句话) 2 极简数据流 3 最小依赖实现(本地 SQLite + OpenAI 兼容端点) 3.1 一次性准备:Excel → SQLite 3.2 关键词提取 + 查表(正则 / SQL) 3.3 单次 LLM 调用 4 运行结果示例 5 性能 & Token 对比 6 可扩展点 7 参考…

(转)mybatis和hibernate的 缓存区别?

MyBatis 和 Hibernate 都是流行的 Java 持久化框架&#xff0c;它们都提供了自己的缓存机制来优化数据库操作&#xff0c;减少数据库的访问次数&#xff0c;提高应用程序的性能。尽管两者都支持缓存&#xff0c;但是它们的缓存实现方式和配置有所不同。1. 缓存机制的基本区别My…

【linux内核系列】:万字详解进程间通信:消息队列

&#x1f525; 本文专栏&#xff1a;Linux &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 你讨厌的现在&#xff0c;是未来的你拼命想回去修正的战场。 ★★★ 本文前置知识&#xff1a; 匿名管道 命名管道 共享内存 前…

React 19 革命性升级:编译器自动优化,告别手动性能调优时代

概述 React 19 是 React 框架的一个重要里程碑版本&#xff0c;带来了众多突破性的改进和新特性。本文档将详细介绍 React 19 的主要变化&#xff0c;帮助开发者了解并迁移到新版本。 &#x1f680; 主要新特性 React Compiler (编译器) React 19 引入了全新的 React Compi…

UE5的渲染Debug技巧

ShaderPrint UE5相对UE4使用的ComputeShader(GPU Driven)的地方多很多。因为UE5为了方便查看ComputeShader的某些值&#xff0c;开发了“ShaderPrint”&#xff0c;方便直接在Shader 打印信息到屏幕&#xff0c;而不用采用CPUReadback在print的方式。 比如r.nanite.ShowStats…

【2025/08/03】GitHub 今日热门项目

GitHub 今日热门项目 &#x1f680; 每日精选优质开源项目 | 发现优质开源项目&#xff0c;跟上技术发展趋势 &#x1f4cb; 报告概览 &#x1f4ca; 统计项&#x1f4c8; 数值&#x1f4dd; 说明&#x1f4c5; 报告日期2025-08-03 (周日)GitHub Trending 每日快照&#x1f55…

Android系统模块编译调试与Ninja使用指南

模块编译调试方法 (此处举例framework、installd、SystemUI等模块的编译调试&#xff0c;其他类似) 1. Framework模块编译 Android系统代码的framework目录内&#xff0c;一共有3个模块单独编译&#xff1a;framework、services、framework-res.apk。 注意&#xff1a;偶尔会有…

【硬件-笔试面试题】硬件/电子工程师,笔试面试题-51,(知识点:stm32,GPIO基础知识)

目录 1、题目 2、解答 3、相关知识点 一、GPIO 基本结构与特性 1. GPIO 硬件结构 2. 主要特性 二、GPIO 工作模式 1. 输入模式 2. 输出模式 3. 复用功能模式 4. 特殊模式 三、GPIO 配置步骤&#xff08;以 STM32Cube HAL 库为例&#xff09; 1. 初始化 GPIO 时钟 …

小智服务器Java安装编译(xinnan-tech)版

github&#xff1a;https://github.com/xinnan-tech/xiaozhi-esp32-server 一、JDK 1、JDK21下载&#xff1a; https://www.oracle.com/cn/java/technologies/downloads/#jdk21-windows RPM安装&#xff1a; rpm -ivh jdk-21_linux-x64_bin.rpm 2、IDEA设置JDK File → P…

智能平台的感知进化:AI × 视频通感在群体终端协同中的应用探索

✳️ 引言&#xff1a;从单兵到集群&#xff0c;未来智能平台的协同演进 从传统的单兵执行任务到如今的“群体智能平台编组”&#xff0c;现代感知系统正经历一场由 AI、机器人与智能计算平台驱动的深度变革。过去&#xff0c;履带式无人平台在平坦地形中承担支援任务&#xf…

基于定制开发开源AI智能名片S2B2C商城小程序的B站私域流量引流策略研究

摘要&#xff1a;随着移动互联网进入存量竞争阶段&#xff0c;私域流量运营成为企业数字化转型的核心战略。B站作为中国最大的Z世代文化社区&#xff0c;其3.41亿月活跃用户中Z世代占比达58%&#xff0c;且25岁以上用户增速显著&#xff0c;用户日均使用时长超108分钟&#xff…

Spring+K8s+AI实战:3全栈开发指南

Spring、K8s、人工智能、Docker及Windows实例 以下是与Spring、K8s、人工智能、Docker及Windows实例相关的实用示例,涵盖开发、部署和集成场景: Spring Boot微服务开发 示例1:REST API构建 使用Spring Boot创建带Swagger文档的RESTful服务,集成JPA和Hibernate进行数据库…

C++ 生成动态库.dll 及 C++调用DLL,C++ 生成静态库.lib及 C++调用lib

文章目录1 C 动态库.dll生成 及 调用1.1 生成C 动态库dll1.1.1 创建项目MyDLL1.1.2 编写.h 和 .cpp文件1.1.3 设置 及 生成 DLL1.2 调用 C 动态库dll1.2.1 创建C 空项目DLLtest1.2.2 动态库配置 及代码调用测试2 C 静态库.lib 生成 及 调用3 C 生成静态库.lib及调用 &#xff0…

信创应用服务器TongWeb安装教程、前后端分离应用部署全流程

TongWeb 简介TongWeb 是东方通&#xff08;TongTech&#xff09;开发的国产Java应用服务器&#xff08;中间件&#xff09;&#xff0c;类似于国外的 WebLogic、WebSphere 和开源的 Tomcat、Jetty&#xff0c;主要用于企业级Java应用&#xff08;如J2EE&#xff09;的部署和运行…

Rust 同步方式访问 REST API 的完整指南

Rust 同步方式访问 REST API 的完整指南 在 Rust 中不使用异步机制访问 REST API 是完全可行的&#xff0c;特别适合简单应用、脚本或不需要高并发的场景。以下是完整的同步实现方案&#xff1a; &#x1f4e6; 依赖选择 推荐库&#xff1a; [dependencies] reqwest { version…

32.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--财务服务--账本与预算

在我们的孢子记账应用中&#xff0c;账本是用于记录每一笔收支流水的核心模块。通过账本&#xff0c;我们可以清晰地追踪资金的流入与流出&#xff0c;进行数据统计和分析&#xff0c;为后续的报表生成和决策支持提供基础数据。预算模块则是用于设置和管理预算的功能&#xff0…

模型预估打分对运筹跟踪的影响

在uplift建模中&#xff0c;模型离线指标(QINI、AUUC)提升并不意味着在线A/B实验的收益&#xff0c;因为在线运筹还需要λ\lambdaλ约束。如果模型打分不满足单调增且roi边际递减&#xff0c;那么λ\lambdaλ运筹求解会非常不稳定&#xff0c;导致线上发券偏高&#xff0c;毛利…

音视频学习(四十六):声音的三要素

声音是人类感知世界的重要途径之一。在自然界中&#xff0c;声波本质上是介质中传播的机械振动&#xff0c;而人类对声音的主观感受主要通过三种属性来认知和描述&#xff0c;即音调&#xff08;音高&#xff09;、响度&#xff08;强弱&#xff09;、音色&#xff08;音质&…

spring batch处理数据模板(Reader-Processor-Writer模式)

步骤监听器 Component public class StepListener implements StepExecutionListener {private StepExecution stepExecution;public StepExecution getStepExecution() {return this.stepExecution;}Overridepublic void beforeStep(StepExecution stepExecution) {this.stepE…