二叉树优选算法(一)

一、根据二叉树创建字符串

题目介绍:

给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。

空节点使用一对空括号对 "()" 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

f64c4cfac0024e5a8e90f1e107d52399.png

  • 树中节点的数目范围是 [1, 104]
  • -1000 <= Node.val <= 1000

思路:

这个题就是一个简单的开胃菜,思路就是在前序遍历的过程中先将所有子树都用括号括起来,最后看哪些括号可以省略,观察可以发现,如果左子树不为空,右子树为空,那么右子树括号就可以省略,如果左子树为空,右子树不为空,那左子树的括号不能省略,所以右子树存在就打印括号,不存在就不打印,而左子树存在则一定打印,如果为空的话就要看右子树是否存在

class Solution {
public:
    string tree2str(TreeNode* root) {
        string str;
        if (root == nullptr)
            return str;

        str += to_string(root->val);
        
        if (root->left||(root->left==nullptr&&root->right)) {
            str += '(';
            str+=tree2str(root->left);
            str += ')';
        }

        if (root->right) {
            str += '(';
            str+=tree2str(root->right);
            str += ')';
        }
        return str;
    }
};

二、二叉树的层序遍历

题目介绍:
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

5e51f3da9a724c7ca46eb3ddc01ea227.png

思路1:

对于层序遍历来说很简单,只需要利用一个队列即可,首先将根节点放入队列,在每次出一个节点时,就将这个节点的左右结点放入队列,直到队列为空就遍历完成了,但是这个题目要求我们将每一层的节点数据放到一个数组中,但是我们不知道队列中的每个数据是哪一层的,所以我们可以再创建一个队列,用于记录对应节点的层数

这里就需要两层循环,一层遍历每一层,一层遍历每一层的数据

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> vv;
        queue<TreeNode*> q; // 保存结点
        queue<int> qlevel;  // 保存结点的层数
        int level = 1;
        if (root) {
            q.push(root);
            qlevel.push(level);
        }

        while (!q.empty()) {
             vector<int> v;
            while (level == qlevel.front()) {
                   qlevel.pop();
                TreeNode* node = q.front();
                q.pop();
                v.push_back(node->val);

                if (node->left) {
                    q.push(node->left);
                    qlevel.push(level+1);
                }
                if (node->right) {
                    q.push(node->right);
                    qlevel.push(level+1);
                }
            }
            level++;
            vv.push_back(v);
        }
        return vv;
    }
};

思路2:

基于思路1进行优化,我们无非就是需要知道队列中的数据是对应哪一层的,如果我们知道每一层的数据个数,那就很容易控制队列,所以我们就在遍历完一层后,可以根据队列中的数据个数确定下一层的数据个数levelSize,因为上一层的数据都被出去了,而下一层的数据也都被放入队列了。

和上面一样这里也是两层循环

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> vv;
        queue<TreeNode*> q;
        int leveSize=0;
        if (root) {
            q.push(root);
            leveSize = 1;
        }
        while (leveSize > 0) {
            vector<int> v;
            while (leveSize--) {
                TreeNode* node = q.front();
                v.push_back(node->val);
                q.pop();

                if (node->left) {
                    q.push(node->left);
                }
                if (node->right) {
                    q.push(node->right);
                }
            }
            leveSize = q.size();
            vv.push_back(v);
        }
        return vv;
    }
};

补充:

这里还有一个类似的引申题目

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

dafa7a7694d044bfb4bbcdb8e379a586.png

与上述题目不同的是,他的要求是倒着遍历,那我们可以先正向遍历,最后将结果翻转一下

reverse(vv.begin(), vv.end());

三、二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

6e3ece98bef242b8921550ed94d5f1d5.png

思路1:

最近公共祖先有两种情况,如果一个节点1在另一个节点2的子树中,那节点2就是公共祖先。如果不是上述的情况,那这两个节点一定一个在公共祖先的左边,一个在右边。

对于一个节点来说,p和q和他的位置关系有三种

  • 一个在左一个在右(找到了)
  • 都在左(那公共节点一定在左边,往左边找)
  • 都在右(那公共节点一定在右边,往右边找)
class Solution {
public:
    bool IsChildTree(TreeNode* root, TreeNode* x) {
        if (root == nullptr)
            return false;

        if (root == x)
            return true;

        return IsChildTree(root->left, x) || IsChildTree(root->right, x);
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 发现规律:这两个节点一定一个在最近的公共祖先的左边,一个在右边
        // 或者一个节点是另一个节点的子孙节点
        if (root == nullptr)
            return nullptr;

        if (root == p || root == q)
            return root;

        bool pInLeft,pInRight,qInLeft,qInRight;

        pInLeft=IsChildTree(root->left,p);
        pInRight=!pInLeft;
        qInLeft=IsChildTree(root->left,q);
        qInRight=!qInLeft;
        //一个在左一个在右
        if((pInLeft&&qInRight)||(pInRight&&qInLeft))
        {
            return root;
        }
        else if(pInLeft&&qInLeft)  //都在左边
        {
            return lowestCommonAncestor(root->left,p,q);
        }
        else     //都在右边
        {
            return lowestCommonAncestor(root->right,p,q);
        }
    }
};

但是上面的解法时间复杂度比较高,在最坏的情况下可以到达O(n^2),因为每次都需要判断两个节点是不是他的子树,如果这个两个节点在靠下的位置,每次判断都需要遍历查找到最下面

思路2:

如果我们有了两个节点到根节点的路径,那么这个题目就可以转变为链表相交的问题

所以重点就到了如何获取一个节点到跟节点的路径,我们可以利用栈,使用前序遍历这个树,碰到一个节点首先把它入栈,因为即使这个节点不是我们要找的节点,这个节点也可能是路径中的一个分支,然后继续遍历他的两个子树,如果他的两个子树都没找到,说明这个节点一定不属于路径中,就把这个节点弹出去。

当获取到两个节点到根节点的路径,首先让长的路径先走,直到两个链表的长度相同,在一块走,直到找到相交点

class Solution {
public:
    bool GetPath(TreeNode* root, TreeNode* x, stack<TreeNode*>& path) {
        if (root == nullptr)
            return false;

        // 前序遍历的思路,找x结点的路径
        // 遇到root结点先push⼊栈,因为root就算不是x,但是root可能是根->x路径中⼀个分⽀结点             
        path.push(root);
        if (root == x)
            return true;
        if (GetPath(root->left, x, path))
            return true;
        if (GetPath(root->right, x, path))
            return true;

        // 如果左右⼦树都没有x,那么说明上⾯⼊栈的root不是根->x路径中⼀个分⽀结点
        // 所以要pop出栈,回退,继续去其他分⽀路径进⾏查找
        path.pop();

        return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> pPath, qPath;
        GetPath(root, p, pPath);
        GetPath(root, q, qPath);
        // 模拟链表相交,两个路径找交点
        // ⻓的先⾛差距步,再⼀起⾛找交点
        while (pPath.size() != qPath.size()) {
            if (pPath.size() > qPath.size())
                pPath.pop();
            else
                qPath.pop();
        }
        while (pPath.top() != qPath.top()) {
            pPath.pop();
            qPath.pop();
        }
        return pPath.top();
    }
};

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMq死信队列延迟交换机

架构图 配置 package com.example.demo.config;import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class DeadLetterConfig {public String …

JavaWeb学习--cookie和session,实现登录的记住我和验证码功能

目录 &#xff08;一&#xff09;Cookie概述 1.什么叫Cookie 2.Cookie规范 3.Cookie的覆盖 4.cookie的最大存活时间 ​​​​​​&#xff08;Cookie的生命&#xff09; &#xff08;二&#xff09; Cookie的API 1.创建Cookie&#xff1a;new 构造方法 2.保存到客户端浏…

开启第二阶段---蓝桥杯

一、12.10--数据类型的范围及转化 今天是刚开始&#xff0c;一天一道题 对于这道题我想要记录的是Java中的整数默认是 int 类型&#xff0c;如果数值超出了 int 的范围&#xff0c;就会发生溢出错误。为了避免这个问题&#xff0c;可以将数字表示为 long 类型&#xff0c;方法…

黑马头条学习笔记

Day01-环境搭建 项目概述 课程大纲 业务说明 技术栈 Spring-Cloud-Gateway : 微服务之前架设的网关服务&#xff0c;实现服务注册中的API请求路由&#xff0c;以及控制流速控制和熔断处理都是常用的架构手段&#xff0c;而这些功能Gateway天然支持 运用Spring Boot快速开发…

详解RabbitMQ在Ubuntu上的安装

​​​​​​​ 目录 Ubuntu 环境安装 安装Erlang 查看Erlang版本 退出命令 ​编辑安装RabbitMQ 确认安装结果 安装RabbitMQ管理界面 启动服务 查看服务状态 通过IP:port访问 添加管理员用户 给用户添加权限 再次访问 Ubuntu 环境安装 安装Erlang RabbitMq需要…

SpringBoot【二】yaml、properties两配置文件介绍及使用

一、前言 续上一篇咱们已经搭建好了一个springboot框架雏形。但是很多初学的小伙伴私信bug菌说&#xff0c;在开发项目中&#xff0c;为啥.yaml的配置文件也能配置&#xff0c;SpringBoot 是提供了两种2 种全局的配置文件嘛&#xff0c;这两种配置有何区别&#xff0c;能否给大…

Excel的文件导入遇到大文件时

Excel的文件导入向导如何把已导入数据排除 入起始行&#xff0c;选择从哪一行开始导入。 比如&#xff0c;前两行已经导入了&#xff0c;第二次导入的时候排除前两行&#xff0c;从第三行开始&#xff0c;就将导入起始行设置为3即可&#xff0c;且不勾选含标题行。 但遇到大文…

Windows平台Unity3D下RTMP播放器低延迟设计探讨

技术背景 好多开发者希望我们分享下大牛直播SDK是如何在Unity下实现低延迟的RTMP播放的&#xff0c;以下是一些降低 Unity 中 RTMP 播放器延迟的方法&#xff1a; 一、选择合适的播放插件或工具 评估和选用专业的流媒体插件 市场上有一些专门为 Unity 设计的流媒体插件&…

PaddleOCR模型ch_PP-OCRv3文本检测模型研究(一)骨干网络

从源码上看&#xff0c;PaddleOCR一共支持四个版本&#xff0c;分别是PP-OCR、PP-OCRv2、PP-OCRv3、PP-OCRv4。本文选择PaddleOCR的v3版本的骨干网络作为研究对象&#xff0c;力图探究网络模型的内部结构。 文章目录 研究起点卷归层压发层残差层骨干网代码实验小结 研究起点 参…

log4j漏洞复现--vulhub

声明&#xff1a;学习过程参考了同站的B1g0rang大佬的文章 Web网络安全-----Log4j高危漏洞原理及修复(B1g0rang) CVE-2021-44228 RCE漏洞 Log4j 即 log for java(java的日志) &#xff0c;是Apache的一个开源项目&#xff0c;通过使用Log4j&#xff0c;我们可以控制日志信息输…

计算机网络ENSP课设--三层架构企业网络

本课程设计搭建一个小型互联网&#xff0c;并模拟Internet的典型Web服务过程。通过此次课程设计&#xff0c;可以进一步理解Internet的工作原理和协议过程&#xff0c;并提高综合知识的运用能力和分析能力。具体目标包括&#xff1a; &#xff08;1&#xff09;掌握网络拓扑的…

SQL 获取今天的当月开始结束范围:

使用 GETDATE() 结合 DATEADD() 和 DATEDIFF() 函数来获取当前月的开始和结束时间范围。以下是实现当前月时间范围查询的 SQL&#xff1a; FDATE > DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) FDATE < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) 1, 0) …

Go的Gin比java的Springboot更加的开箱即用?

前言 隔壁组的云计算零零后女同事&#xff0c;后文简称 云女士 &#xff0c;非说 Go 的 Gin 框架比 Springboot 更加的开箱即用&#xff0c;我心想在 Java 里面 Springboot 已经打遍天下无敌手&#xff0c;这份底蕴岂是 Gin 能比。 但是云女士突出一个执拗&#xff0c;非我要…

【2024最新Java面试宝典】—— SpringBoot面试题(44道含答案)

1. 什么是 Spring Boot&#xff1f; Spring Boot 是 Spring 开源组织下的子项目&#xff0c;是 Spring 组件一站式解决方案&#xff0c;主要是简化了使用 Spring 的难度&#xff0c;简省了繁重的配置&#xff0c;提供了各种启动器&#xff0c;使开发者能快速上手。 2. 为什么…

【PlantUML系列】用例图(三)

目录 一、组成部分 二、典型案例 一、组成部分 参与者&#xff08;Actors&#xff09;&#xff1a;使用关键字 actor 后跟参与者的名称。用例&#xff08;Use Cases&#xff09;&#xff1a;使用关键字 usecase 后跟用例的名称和编号&#xff08;可选&#xff09;。系统边界…

C++命运石之门代码抉择:C++入门(上)

文章目录 1.前言1.1 什么是C1.2 C的发展1.3 C的重要性1.4 如何学习C1.5 C要学什么 2. C语言过渡到C(上)2.1 域2.1.1 命名空间2.1.1.1 定义2.1.1.2 作用域限定符2.1.1.3 使用 2.1.2 域的使用优先级 2.2 输入及输出2.2.1 std 命名空间及自定义命名空间2.2.2 .C输入&输出 2.3 …

Composer在安装的过程中经常找不到刚更新的包

明明有v2.1.0版本&#xff0c;安装就是找不到这个版本的包。 1. Composer 官方网址&#xff1a;https://getcomposer.org 中文网站&#xff1a;https://www.phpcomposer.com 官方文档&#xff1a;https://docs.phpcomposer.com 2. Packagist Packagist 是 Composer的组件仓库…

Android笔记【14】结合LaunchedEffect实现计时器功能。

一、问题 cy老师第五次作业 结合LaunchedEffect实现计时器功能。要求&#xff1a;动态计时&#xff0c;每秒修改时间&#xff0c;计时的时间格式为“00&#xff1a;00&#xff1a;00”&#xff08;小时&#xff1a;分钟&#xff1a;秒&#xff09;提交源代码的文本和运行截图…

【强化学习入门笔记】 2.1 值迭代

本系列为学习赵世钰老师的《强化学习的数学原理》所作的学习笔记. 本节我们将介绍强化学习中的值迭代求解方法. 2.1.1 算法步骤 在1.5节我们介绍了通过迭代可以求贝尔曼最优公式的最优解, 这个方法就叫值迭代: v k 1 max ⁡ π ∈ Π ( r π γ P π v k ) , k 0 , 1 , …

汽车车牌标记支持YOLO,COCO,VOC三种格式标记,4000张图片的数据集

本数据集支持YOLO&#xff0c;COCO&#xff0c;VOC三种格式标记汽车车牌&#xff0c;无论是新能源汽车还是油车都能识别标记&#xff0c;该数据集一共包含4000张图片 数据集分割 4000总图像数 训练组 70&#xff05; 2800图片 有效集 20&#xff05; 800图片 测…