首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

LeetCode513. 找树左下角的值

编程知识
2024年07月25日 14:38

题目链接:https://leetcode.cn/problems/find-bottom-left-tree-value/description/

题目叙述:

给定一个二叉树的 根节点 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. 我们递归函数要传入的参数和递归函数的返回值
  2. 递归结束的条件(也就是递归的边界)
  3. 单层递归的逻辑

其实本题当中递归里面也蕴含着回溯的逻辑,其实所有的递归算法都离不开回溯,只是我们没有意识到回溯的过程,或者说回溯的过程被隐藏掉了。

下面的代码中我会重点强调回溯的逻辑

步骤1.确定我们的参数和返回值

这题的参数,既然是要求最后一层的最左边的节点,那么我们必然要使用一个参数depth来表示深度,然后我们也需要一个参数maxdepth来表示当前是否是达到了最大的深度,不过这个maxdepth变量不需要

传入函数中,我们可以定义为全局变量,如果depth>maxdepth,就证明当前还未到达最大深度,也就不是我们要处理的最左边的节点了。 同时,我们还需要一个参数result来接收我们需要求得这个节点的节点

值,这个变量我们也定义为全局变量。

确定递归的中止条件

我们要处理的是什么节点?是不是叶子节点,我们处理叶子节点的逻辑判断是什么?是不是只需要当前这个节点它的左右孩子都为空的时候,我们就到达了我们需要处理的时候了,这个时候就是返回的时候了。

那我们要处理这个节点,要做些什么事情呢?——我们要判断当前深度是否是最大深度,如果不是,我们就得更新这个最大深度,同时我们要更新result变量的值,然后再返回,这样就处理好了递归的边界条件,

对吧?

这段逻辑的代码如下:

       //处理到叶子节点就返回
        if(cur->left==NULL&&cur->right==NULL){
            if(depth>maxdepth){
                maxdepth=depth;
                result=cur->val;
            }
            return;
        }

单层递归的逻辑

我们现在找到了最深层次的叶子节点,那么我们如何保证它一定是最左边的节点呢?那还不简单嘛!只需要我们处理递归的时候,优先处理左子树,不就能保证我们先处理的是左孩子了嘛!对吧,

这段逻辑的代码如下:

            if(cur->left!=NULL){
            //先让depth++,让他处理下一层的节点
            depth++;
            traversal(cur->left,depth);
            //再让depth--,这就是回溯的过程,退到上一层的节点,再处理右边的子树
            depth--;
        }
            if(cur->right!=NULL){
            //这里也是一样的道理
            depth++;
            traversal(cur->right,depth);
            //这里也是回溯的过程
            depth--;
        }

其实,处理好了这几个边界条件,我们的代码就出来了

整体代码:

class Solution {
public:
    int result=0;
    int maxdepth=INT_MIN;
    void traversal(TreeNode*cur,int depth){
        //处理到叶子节点就返回
        if(cur->left==NULL&&cur->right==NULL){
            if(depth>maxdepth){
                maxdepth=depth;
                result=cur->val;
            }
            return;
        }
            if(cur->left!=NULL){
            //先让depth++,让他处理下一层的节点
            depth++;
            traversal(cur->left,depth);
            //再让depth--,这就是回溯的过程,退到上一层的节点,再处理右边的子树
            depth--;
        }
            if(cur->right!=NULL){
            //这里也是一样的道理
            depth++;
            traversal(cur->right,depth);
            //这里也是回溯的过程
            depth--;
        }
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root,0);
        return result;
    }
};

层序遍历(迭代法)

其实,这题使用层序遍历才是最方便,最简单的做法。我们只需要处理每一层的第一个元素,然后处理到最后一层,它自然就是最后一层的左边第一个元素了,这题只需要在层序遍历的模板上面改动一点点

就可以实现了!

如果不会层序遍历的话,推荐去看看我的层序遍历的文章,里面详细讲解了层序遍历实现的过程!

层序遍历:https://www.cnblogs.com/Tomorrowland/p/18318744

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        int result = 0;
        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;
    }
};
From:https://www.cnblogs.com/Tomorrowland/p/18323306
本文地址: http://www.shuzixingkong.net/article/423
0评论
提交 加载更多评论
其他文章 Rust 中 *、&、mut、&mut、ref、ref mut 的用法和区别
*:解引用操作符,用于访问指针或引用指向的值的类型。 &:借用操作符,用于创建不可变引用的类型,允许只读访问。 mut:关键字,用于声明可变变量或参数的类型,允许其值被修改。 &mut:借用操作符,用于创建可变引用的类型,允许读写访问。 ref:模式匹配中的关键字,用于创建不可变引用的类型,避免所有
整段 html实现其中的每一个 a 标签跨域下载操作 window.URL.createObjectURL(blob)
window.URL.createObjectURL(blob) a 标签下载问题,通常在 a 标签中加上download属性,就可完成对href属性链接文件的下载,但仅仅是限于同源文件,如果是非同源,download 属性就会失效 第一种情况,单独的一个标签实现下载,可以使用 span 标签+cl
Cython与C函数的结合
这篇文章介绍了Python-Cython-C三种语言的简单耦合,以Cython为中间接口,实现Python数据传到C语言的后端执行相关计算。这就相当于可以在Python中调用C语言中的指针功能来进行跨维度的数组运算,至于性能依然存在优化空间,这里仅仅做一个简单的功能演示。
Nuxt.js 环境变量配置与使用
title: Nuxt.js 环境变量配置与使用 date: 2024/7/25 updated: 2024/7/25 author: cmdragon excerpt: 摘要:“该文探讨了Nuxt.js框架下环境变量配置的详细过程,涉及.env文件配置、运行时访问、安全性考量、在不同场景下的实践(
Nuxt.js 环境变量配置与使用 Nuxt.js 环境变量配置与使用
三星app移植修复(app反编译修改)
工具: apktool ADT 命令: 反编译 java -jar apktool.jar d test.apk 重打包 java -jar apktool.jar b test 签名使用ADT smail语言粗略理解(其实对于修改来说, 大概熟悉就就ok) 类定义 .class public Lc
三星app移植修复(app反编译修改) 三星app移植修复(app反编译修改) 三星app移植修复(app反编译修改)
深入探讨Spring Boot中的参数传递
深入探讨Spring Boot中的参数传递 在Spring Boot开发中,参数传递是一个非常常见且重要的操作。无论是处理HTTP请求,还是在方法之间传递数据,理解和掌握参数传递的各种方式都能让我们的代码更加简洁和高效。今天,我们就来深入探讨一下Spring Boot中的参数传递。 1. 基础知识:
RIME:用交叉熵 loss 大小分辨 preference 是否正确 + 内在奖励预训练 reward model
① 假设正确样本的 CELoss 上限是 ρ,可推出错误样本相对 P_ψ(x) 分布的 KL 散度上限,从而筛出可信样本、翻转不可信样本;② 用归一化到 (-1,1) 的 intrinsic reward 预训练 reward model。
ThinkPHP一对一关联模型的运用(ORM)
一、序言 最近在写ThinkPHP关联模型的时候一些用法总忘,我就想通过写博客的方式复习和整理下一些用法。 具体版本: topthink/framework:6.1.4 topthink/think-orm:2.0.61 二、实例应用 1、一对一关联 1.1、我先设计了两张表,分别为用户表(user
ThinkPHP一对一关联模型的运用(ORM) ThinkPHP一对一关联模型的运用(ORM) ThinkPHP一对一关联模型的运用(ORM)