day16 | 513.找树左下角的值 112.路径总和 106.从中序与后序遍历序列构造二叉树

news2024/12/27 14:45:24

文章目录

    • 一、找树左下角的值
    • 二、路径总和
    • 三、从中序与后序遍历序列构造二叉树

一、找树左下角的值

513.找树左下角的值

暴力解法

class Solution
{
public:
    int findBottomLeftValue(TreeNode *root)
    {
        // 第一眼想到的就是层序遍历,取最后一层的第一个值即可
        queue<TreeNode *> q;
        q.push(root);
        int res;
        while (!q.empty())
        {
            int size = q.size(); // 记录每一层的节点数
            for (int i = 0; i < size; i++)
            {
                TreeNode *tmp = q.front();
                q.pop();
                if (i == 0)
                    res = tmp->val; // 每次for循环都要更新 i==0 的第一个元素
                if (tmp->left)
                    q.push(tmp->left);
                if (tmp->right)
                    q.push(tmp->right);
            }
        }
        return res;
    }
};

递归法

1、递归如何判断是最后一行呢?

深度最大的叶子节点一定是最后一行。

2、如何判断最左边的叶子节点?

采用前序遍历,优先访问最左边的节点。保证优先左边搜索,然后记录深度最大的叶子节点(这里会return),此时就是树的最后一行最左边的值。

3、为啥没有中?

因为本题没有 中间节点 的处理逻辑,只要左优先就行。

递归函数的参数和返回值:

private:
    int maxDepth = INT_MIN; // 记录最大递归深度
    int res; // 记录最左边的值
public:
    void travelsal(TreeNode* root)
    {}

终止条件:
当遇到叶子节点的时候,就需要统计一下最大的深度了,所以需要遇到叶子节点来更新最大深度。

if (root->left == nullptr && root->right == nullptr)
{
    if (depth > maxDepth)
    {
        maxDepth = depth;
        res = root->val;
    }
    return;
}

单层递归逻辑:

// 前序
if (root->left)
{ // 左
    depth++;
    travelsal(root->left, depth);
    depth--;
}
if (root->right)
{ // 右
    depth++;
    travelsal(root->right, depth);
    depth--;
}

完整代码

class Solution
{
private:
    int maxDepth = INT_MIN;
    int res;

public:
    void travelsal(TreeNode *root, int depth)
    {
        if (root->left == nullptr && root->right == nullptr)
        {
            if (depth > maxDepth)
            {
                maxDepth = depth;
                res = root->val;
            }
            return;
        }

        // 前序
        if (root->left)
        { // 左
            depth++;
            travelsal(root->left, depth);
            depth--;
        }
        if (root->right)
        { // 右
            depth++;
            travelsal(root->right, depth);
            depth--;
        }

        // 为啥没有中?
    }
    int findBottomLeftValue(TreeNode *root)
    {
        travelsal(root, 0);
        return res;
    }
};

二、路径总和

112.路径总和

递归函数的参数和返回值:

bool travelsal(TreeNode *node, int sum){}

注意:这里的sum,是用tar减去当前节点的值来判断。用递减,让计数器sum初始为目标和,然后每次减去遍历路径节点上的数值。

终止条件:

// 终止条件:1、遇到叶子但是值不满足tar 2、遇到叶子且值满足tar
if (node->left == nullptr && node->right == nullptr && sum == 0)
    return true;
if (node->left == nullptr && node->right == nullptr)
    return false;

单层递归逻辑:

// 单层处理逻辑
if (node->left)
{
    sum -= node->left->val;
    if (travelsal(node->left, sum))
        return true;
    sum += node->left->val;
}
if (node->right)
{
    sum -= node->right->val;
    if (travelsal(node->right, sum))
        return true;
    sum += node->right->val;
}
return false;

完整代码:

class Solution
{
public:
    bool travelsal(TreeNode *node, int sum)
    {
        // 终止条件:1、遇到叶子但是值不满足tar 2、遇到叶子且值满足tar
        if (node->left == nullptr && node->right == nullptr && sum == 0)
            return true;
        if (node->left == nullptr && node->right == nullptr)
            return false;

        // 单层处理逻辑
        if (node->left)
        {
            sum -= node->left->val;
            if (travelsal(node->left, sum))
                return true;
            sum += node->left->val;
        }
        if (node->right)
        {
            sum -= node->right->val;
            if (travelsal(node->right, sum))
                return true;
            sum += node->right->val;
        }
        return false;
    }

    bool hasPathSum(TreeNode *root, int tar)
    {
        if (root == nullptr)
            return false;
        return travelsal(root, tar - root->val);
    }
};

1、为啥要if(travelsal(node->left, sum))?
因为递归函数的返回值是bool,需要返回给上层,来判断下层的调用结果。

三、从中序与后序遍历序列构造二叉树

106.从中序与后序遍历序列构造二叉树
在这里插入图片描述

非常经典的一个题目。

一共有6步骤:

  • 第一步:后序数组的size为0,说明是空节点了
  • 第二步:后序数组最后一个元素为根节点
  • 第三步:寻找中序数组(第二步的根节点元素)作为切割点
  • 第四步:切割中序数组
  • 第五步:切割后序数组
  • 第六步:递归处理做区间和右区间

递归函数的参数和返回值:

TreeNode* travelsal(vector<int>& inorder, vector<int>& postorder){
     
 }

终止条件:

if (postorder.size() == 0)
    return nullptr;
int rootval = postorder[postorder.size() - 1];
TreeNode *root = new TreeNode(rootval);
if (postorder.size() == 1)
    return root;

单层递归逻辑:

int index = 0; // 用这个index来保存 中序数组里面根节点(后续数组中的最后一个元素)
for (; index < inorder.size(); index++)
{
    if (inorder[index] == rootval)
    {
        break;
    }
}
// 切割中序数组
// [ , ) 左闭右开
vector<int> leftInorder(inorder.begin(), inorder.begin() + index);
vector<int> rightInorder(inorder.begin() + index + 1, inorder.end());

// postorder 舍弃末尾元素
postorder.resize(postorder.size() - 1);

// 切割后序数组  切割后序数组,是利用的中序数组中左区间的大小来切割的
vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());

// 递归处理左右
root->left = travelsal(leftInorder, leftPostorder);
root->right = travelsal(rightInorder, rightPostorder);
return root;

完整代码:

class Solution
{
public:
    TreeNode *travelsal(vector<int> &inorder, vector<int> &postorder)
    {
        if (postorder.size() == 0)
            return nullptr;
        int rootval = postorder[postorder.size() - 1];
        TreeNode *root = new TreeNode(rootval);
        if (postorder.size() == 1)
            return root;

        int index = 0; // 用这个index来保存 中序数组里面根节点(后续数组中的最后一个元素)
        for (; index < inorder.size(); index++)
        {
            if (inorder[index] == rootval)
            {
                break;
            }
        }
        // 切割中序数组
        // [ , ) 左闭右开
        vector<int> leftInorder(inorder.begin(), inorder.begin() + index);
        vector<int> rightInorder(inorder.begin() + index + 1, inorder.end());

        // postorder 舍弃末尾元素
        postorder.resize(postorder.size() - 1);

        // 切割后序数组  切割后序数组,是利用的中序数组中左区间的大小来切割的
        vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
        vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());

        // 递归处理左右
        root->left = travelsal(leftInorder, leftPostorder);
        root->right = travelsal(rightInorder, rightPostorder);
        return root;
    }
    TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder)
    {
        return travelsal(inorder, postorder);
    }
};

ps:中序+前序也是能够唯一确定一棵二叉树

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

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

相关文章

Vue系列第六篇:axios封装,登录逻辑优化,404页面实现,Go语言跨域处理

第五篇利用vue实现了登录页面&#xff0c;用go语言开发了服务端并最后在nginx上进行了部署。本篇将axios封装&#xff0c;登录逻辑优化&#xff0c;404页面实现。 目录 1.前端 1.1代码结构 1.2源码 2.服务端 2.1源码 3.运行效果 4.注意事项 4.1webpack.config.js和vue…

探索自除数:发现区间内的神奇数字

本篇博客会讲解力扣“728. 自除数”的解题思路&#xff0c;这是题目链接。 对于给定的正整数num&#xff0c;我们如何判断它是不是自除数呢&#xff1f;根据定义&#xff0c;我们只需要把num的每一位数字都取出来&#xff0c;判断能不能整除num&#xff0c;如果发现num的某一位…

【虹科案例】使用虹科模块化数字化仪进行车辆测试

引言 模块化仪器比传统仪器的尺寸大大减小&#xff0c;适合安装在电路卡上&#xff0c;同时也可以将多个卡插入具有通用计算机接口、电源和互连的框架中。模块化仪器框架包括使用标准 PCIe 接口的计算机、PXI 测试框架或基于 LXI 的盒子&#xff0c;工程师通常会使用多个卡并将…

git stash clear清空本地暂存代码

git stash clear清空本地暂存代码 git stash 或者 git stash list 查看本地暂存的代码。 清除本地暂存的代码修改&#xff1a; git stash clear git回退代码仓库版本_git回退到之前的版本会影响本地代码嘛_zhangphil的博客-CSDN博客git回退代码版本_git回退到之前的版本会影…

基于opencv的几种图像滤波

一、介绍 盒式滤波、均值滤波、高斯滤波、中值滤波、双边滤波、导向滤波。 boxFilter() blur() GaussianBlur() medianBlur() bilateralFilter() 二、代码 #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> …

01 制作Windows11启动盘及安装 || 包含校验ISO映像的方法

前言 由于空间越来越不够用了&#xff0c;上次为Ubuntu分配了96G的空间依然是快要被用完&#xff0c;连一个数据集都放不下了&#xff0c;因此我不得不选择换硬盘。 由于是离谱的华为Mate book D 15的2021款逆天机型&#xff0c;我没有第二个硬盘位。至于说移动硬盘的解决方案…

python3GUI--我的翻译器By:PyQt5(附下载地址)

文章目录 一&#xff0e;前言二&#xff0e;展示1.主界面2.段落翻译3.单词翻译 三&#xff0e;设计1.UI设计2.软件设计3.参考 四&#xff0e;总结 一&#xff0e;前言 很早之前写过一篇python3GUI–翻译器By:PyQt5&#xff08;附源码&#xff09; &#xff0c;但是发现相关引擎…

LED显示屏技术:数码时代的绚丽舞台

随着信息技术的飞速发展&#xff0c;LED显示屏技术成为现代社会不可或缺的一部分。这种技术以其高亮度、高清晰度和多样化的应用领域&#xff0c;在数字化时代展现出绚丽多彩的画面&#xff0c;为我们带来了前所未有的视觉体验。本文将探讨LED显示屏技术的原理、应用以及对于现…

【JavaEE】简单了解JVM

目录 一、JVM中的内存区域划分 二、JVM的类加载机制 1、类加载的触发时机 2、双亲委派模型 1.1、向上委派 1.2、向下委派 三、JVM中的垃圾回收机制&#xff08;GC&#xff09; 1、确认垃圾 1.1、引用计数&#xff08;Java实际上没有使用这个方案&#xff0c;但是Pytho…

超详细 | 模拟退火算法及其MATLAB实现

模拟退火算法(simulated annealing&#xff0c;SA)是20世纪80年代初期发展起来的一种求解大规模组合优化问题的随机性方法。它以优化问题的求解与物理系统退火过程的相似性为基础&#xff0c;利用Metropolis算法并适当地控制温度的下降过程实现模拟退火&#xff0c;从而达到求解…

RK3588平台开发系列讲解(调试篇)如何进行性能分析

文章目录 一、什么是性能分析呢?二、系统级工具三、源码级工具沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍性能分析(Performance Profiling) 最简单的性能分析工具是 top,可以快速查看进程的 CPU、内存使用情况;pstack 和 strace 能够显示进程在用…

大数据面试题:HBase的RegionServer宕机以后怎么恢复的?

面试题来源&#xff1a; 《大数据面试题 V4.0》 大数据面试题V3.0&#xff0c;523道题&#xff0c;679页&#xff0c;46w字 可回答&#xff1a;1&#xff09;HBase一个节点宕机了怎么办&#xff1b;2&#xff09;HBase故障恢复 参考答案&#xff1a; 1、HBase常见故障 导…

简要介绍 | 解析模态之间的联系:跨模态学习与多模态学习的区别和联系

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对跨模态学习和多模态学习进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 解析模态之间的联系&#xff1a;跨模态学习与多模态学习的区别和联系 在人工智能的广泛领域中&#xff0c;跨模态学习…

森林中的兔子(力扣)数学思维 JAVA

森林中有未知数量的兔子。提问其中若干只兔子 “还有多少只兔子与你&#xff08;指被提问的兔子&#xff09;颜色相同?” &#xff0c;将答案收集到一个整数数组 answers 中&#xff0c;其中 answers[i] 是第 i 只兔子的回答。 给你数组 answers &#xff0c;返回森林中兔子的…

Python自动化办公-文件整理脚本

哈喽大家好&#xff0c;今天给大家介绍python自动化办公-文件整理脚本 今天讲解文件整理脚本的实现过程。这是一个很有用的技能&#xff0c;可以帮助你管理你的电脑上的各种文件。需求如下&#xff1a; 需求内容&#xff1a;给定一个打算整理的文件夹目录&#xff0c;这个脚本…

django实现部门表的增删改查界面

1、前期准备 部署好mysql数据库&#xff0c;创建好unicom数据库下载好bootstap的插件下载好jquery的插件下载好mysqlclient-1.4.6-cp36-cp36m-win_amd64.whl的安装包&#xff0c;根据python的版本下载 2、创建项目 在pycharm中创建项目 在pycharm的终端创建虚拟环境 py -m v…

【软件测试】性能测试工具- LoadRunner的介绍和使用

目录 1. LoadRunner是什么2. LoadRunner环境搭建3. LoadRunner三大组件4. LoadRunner脚本录制4.1 WebTous项目介绍启动WebTous项目访问WebTous项目相关配置 4.2 脚本录制新建脚本录制脚本运行脚本 4.3 脚本加强插入事务插入集合点插入检查点插入日志字符串比较 1. LoadRunner是…

Nyan Progress Bar 更换进度条插件

打开idea 每天面对进度条怪无聊的&#xff0c;今天无意之中发现一个插件还挺有意思的 Nyan Progress Bar 当然啦&#xff0c;根据自己的喜欢进行选择 安装好之后&#xff0c;然后再打开idea

【计算机视觉|人脸建模】SOFA:基于风格、由单一示例的2D关键点驱动的3D面部动画

本系列博文为深度学习/计算机视觉论文笔记&#xff0c;转载请注明出处 标题&#xff1a;SOFA: Style-based One-shot 3D Facial Animation Driven by 2D landmarks 链接&#xff1a;SOFA: Style-based One-shot 3D Facial Animation Driven by 2D landmarks | Proceedings of …

Python 进阶(六):文件读写(I/O)

❤️ 博客主页&#xff1a;水滴技术 &#x1f338; 订阅专栏&#xff1a;Python 入门核心技术 &#x1f680; 支持水滴&#xff1a;点赞&#x1f44d; 收藏⭐ 留言&#x1f4ac; 文章目录 1. 打开文件2. 读取文件2.1 逐行读取文件2.2 读取所有行 3. 写入文件3.1 向文件中写入…