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

513. 找树左下角的值

文章目录

  • 513. 找树左下角的值
  • 递归
  • 迭代法
  • 总结

513. 找树左下角的值

513. 找树左下角的值

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

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

示例 1:
在这里插入图片描述

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

示例 2:
在这里插入图片描述

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

提示:

  • 二叉树的节点个数的范围是 [1,10^4]
  • -2^31 <= Node.val <= 2^31 - 1

思路

本题要找出树的最后一行的最左边的值。此时大家应该想起用层序遍历是非常简单的了,反而用递归的话会比较难一点。

我们依然还是先介绍递归法。

递归

咋眼一看,这道题目用递归的话就就一直向左遍历,最后一个就是答案呗?

没有这么简单,一直向左遍历到最后一个,它未必是最后一行啊。

我们来分析一下题目:在树的最后一行找到最左边的值。

首先要是最后一行,然后是最左边的值。

如果使用递归法,如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。

所以要找深度最大的叶子节点。

那么如何找最左边的呢?可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。

递归三部曲:

  1. 确定递归函数的参数和返回值
    参数必须有要遍历的树的根节点,还有就是一个int型的变量用来记录当前深度,

本题还需要两个指针变量(因为递归过程中需要全局的改变他们的值),maxDepth用来记录最大深度,res记录最大深度最左节点的数值。

代码如下:

func dfs(root *TreeNode,res *int,depth int,maxDepth *int) {}
  1. 确定终止条件

代码如下:

if root == nil {
      return 
  }
  1. 确定单层递归的逻辑
    遍历到空节点时返回即可。最大深度更新时,说明初次到达新的一层,此时的节点其实就是当前层最左的节点,可以更新结果。递归的过程中依然要使用回溯,代码如下:
// 深度增加了,肯定是初次遍历到某层时深度比最大深度还大了,此时的节点就是当前层的最左节点
  if depth > *maxDepth {
      *res = root.Val
      *maxDepth = depth
  }

  if root.Left != nil {
      depth++
      dfs(root.Left,res,depth,maxDepth)
      depth--
      // 上面三行是故意这么写的,更清楚的看到回溯过程,实际三行可以写成下面一行
      // dfs(root.Left,res,depth+1,maxDepth)
  }

  if root.Right != nil {
      dfs(root.Right,res,depth+1,maxDepth)
  }

完整Go代码如下:

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findBottomLeftValue(root *TreeNode) int {
    // 采用前中后序遍历都可以,因为只要能保证左节点比右节点先访问就可以啦
    // 第一次进入最大深度的就是最底层最左边的节点
    if root == nil {
        return 0
    }
    res := 0
    maxDepth := math.MinInt32
    dfs(root,&res,1,&maxDepth) // 根节点认为是第一层
    return res
}

func dfs(root *TreeNode,res *int,depth int,maxDepth *int) {
    if root == nil {
        return 
    }
    // 深度增加了,肯定是初次遍历到某层时深度比最大深度还大了,此时的节点就是当前层的最左节点
    if depth > *maxDepth {
        *res = root.Val
        *maxDepth = depth
    }

    if root.Left != nil {
        depth++
        dfs(root.Left,res,depth,maxDepth)
        depth--
        // 上面三行是故意这么写的,更清楚的看到回溯过程,实际三行可以写成下面一行
        // dfs(root.Left,res,depth+1,maxDepth)
    }

    if root.Right != nil {
        dfs(root.Right,res,depth+1,maxDepth)
    }
}

迭代法

本题使用层序遍历再合适不过了,比递归要好理解得多!

只需要记录最后一行第一个节点的数值就可以了。

代码如下:

func findBottomLeftValue(root *TreeNode) int {
    var res int
    queue := list.New()
    
    queue.PushBack(root)
    for queue.Len() > 0 {
        length := queue.Len()
        for i := 0; i < length; i++ {
            node := queue.Remove(queue.Front()).(*TreeNode)
            if i == 0 {
                res = node.Val
            }
            if node.Left != nil {
                queue.PushBack(node.Left)
            }
            if node.Right != nil {
                queue.PushBack(node.Right)
            }
        }
    }
    return res
}

总结

本题涉及如下几点:

  • 递归求深度的写法,每进入一层,深度+1
  • 递归中其实隐藏了回溯,上面递归代码时,故意让左右子树写法不同,左子树明确回溯,右子树隐藏了回溯。
  • 层次遍历

本题涉及到的点,我们之前都讲解过,这些知识点需要同学们灵活运用,这样就举一反三了。

相关文章:

  • 常见场景题3(面试)
  • Netty简介
  • 时序数据库 TDengine 的入门体验和操作记录
  • java 框架组件
  • 24暑假实习信息、25秋招提前批信息,地信、测绘、遥感、地质相关岗位招聘汇总
  • C++——输入三个整数,按照由小到大的顺序输出。用指针方法处理。
  • ubuntu错误GPG error: http://repo.mysql.com/apt/ubuntu noble InRelease
  • Contact Form 7最新5.9.8版错误修复方案
  • Redisson 总结
  • QT窗口无法激活弹出问题排查记录
  • Stylized Smooth Clouds 卡通风格化云朵包
  • 《ChatGPT:强大的人工智能聊天机器人》
  • PG逻辑订阅功能
  • 【完整梳理验证】企业微信第三方应用接入全流程java版
  • 大数据新视界 --大数据大厂之探索ES:大数据时代的高效搜索引擎实战攻略
  • 第十四届蓝桥杯嵌入式国赛
  • 瑞利相干斑模型
  • 本地程序管理 -- geek(自带删除注册表内容)
  • Node-RED-L2-Node-RED在Linux系统启动时自动运行
  • php发送邮箱教程:如何实现邮件发送功能?
  • 巴基斯坦总理:希望通过和平对话方式解决与印方问题
  • 王毅同印度国家安全顾问多瓦尔通电话
  • 《尤物公园》连演8场:观众上台,每一场演出都独一无二
  • 韩德洙成为韩国执政党总统大选候选人
  • 图集|俄罗斯举行纪念苏联伟大卫国战争胜利80周年阅兵式
  • “降息潮”延续!存款利率全面迈向“1时代”