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

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.dtcms.com/a/312672.html

相关文章:

  • 【鸿蒙高级】
  • [硬件电路-148]:数字电路 - 什么是CMOS电平、TTL电平?还有哪些其他电平标准?发展历史?
  • 动感按钮:如何打造交互感十足的点击动画效果
  • 【1】WPF界面开发入门—— 图书馆程序:登录界面设计
  • 基于图像识别与分类的中国蛇类识别系统
  • [硬件电路-151]:数字电路 - 模拟电路与数字电路的本质
  • 【数据结构】二叉树的顺序结构实现
  • SQL注入SQLi-LABS 靶场less31-38详细通关攻略
  • 托福阅读38-3
  • 使用AssemblyAI将音频数据转换成文本
  • AI生成图片工具分享!
  • Linux的权限概念
  • 关于Web前端安全之XSS攻击防御增强方法
  • 【视频内容创作】PR的关键帧动画
  • 机器学习第三课之逻辑回归(三)LogisticRegression
  • Python-初学openCV——图像预处理(五)
  • 团队独立思考的力量
  • 论文阅读:DMD蒸馏 | One-step Diffusion with Distribution Matching Distillation
  • Python 动态属性和特性(定义一个特性工厂函数)
  • 「源力觉醒 创作者计划」_文心大模型4.5系列开源模型, 从一行代码到一个生态:聊聊开源战略那些事儿,顺便扯扯文心大模型 4.5 的使用心得
  • zookeeper分布式锁 -- 读锁和写锁实现方式
  • gpu instancer crowd 使用自定义材质并且只修改单个物体的材质参数
  • 【领域热点】【Vue】Vue 与 WebAssembly:前端性能优化的黄金搭档
  • 渗透高级-----应急响应
  • 机器翻译的分类:规则式、统计式、神经式MT的核心区别
  • 新电脑上GitHub推送失败?全面排查与解决指南
  • 第三章-提示词-高级:开启智能交互新境界(13/36)
  • Flutter Dart类的使用
  • WebMvc自动配置流程讲解
  • 【MySQL】MySQL的安全风险与安装安全风险