二叉搜索树在线OJ题讲解

news2024/11/19 5:12:09
二叉树创建字符串

在这里插入图片描述
在这里插入图片描述

我们首先进行题目的解读:
大概意思就是用()把每个节点的值给括起来,然后再经过一系列的省略的来得到最后的结果

大家仔细观察题目给出的列子就可以发现,其实这个题目可以大致分为三种情况:

1 节点的左孩子和右孩子都在,不能省略括号
2 节点没有左孩子只有右孩子,不能省略括号
3 节点没有右孩子只有左孩子,可以省略这个空节点的括号,用来区分第二种情况,保证了一个字符串只能对应一个二叉搜索树

就比如例1:
在这里插入图片描述

例子中给出的初步转化的字符串是没有经过省略的,其实4后面还要加上两个空括号才完美,这里题目有一点小误差

就比如节点2他的右孩子节点是空的,所以那个括号就要省略,4和3的两个括号都省略,就可以得到最后的结果了

代码如下:
我们首先定义一个字符串,如果根节点root为空,就直接返回这个空字符串,不为空先+=root内存储的val
如果root的左孩子节点或者root的右孩子节点不为空的话,就要把root的左孩子节点的val用括号括起来,就算左孩子为空这个括号也不能省略
如果root的右孩子不为空就要把root的右孩子用括号括起来,最后 返回时str即可

class Solution {
public:
    string tree2str(TreeNode* root) 
    {
        string str;
        if(root==nullptr)
            return str;
        str+=to_string(root->val);
        if(root->left||root->right)
       { 
        str+='(';
        str+=tree2str(root->left);
        str+=')';
        }
        if(root->right)
        {
         str+='(';
         str+=tree2str(root->right);
         str+=')';
        }
        return str;
    }
};
二叉树的分层遍历


在这里插入图片描述
这个题目是一个典型的vector里面套vector(int)的题目,他最后返回的是双层结构
在这里插入图片描述
我们可以用到一个队列,这个队列用来存放节点,而双层的vector容器就用来存放层序遍历节点的val,最后返回

我们先将root节点放进队列,然后当他出来后,将他的左右孩子节点放入队列,只要队列不为空不就继续
在这里插入图片描述
完整代码如下:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) 
    {
        queue<TreeNode*> q;
        vector<vector<int>> vv;
        if(root==nullptr)
            return vv;
        int levelsize=0;
        q.push(root);
        levelsize=q.size();
        while(!q.empty())
        {
            vector<int> v;
            while(levelsize--)
        {
            TreeNode* node=q.front();
            q.pop();
            v.push_back(node->val);
            if(node->left)
                q.push(node->left);
            if(node->right)
                q.push(node->right);
        }
        vv.push_back(v);
        levelsize=q.size();
        }
        return vv;
    }
};


在这里插入图片描述
自底向上的层序遍历,我们就偷懒直接用上面的代码,用一个reverse函数反转即可:

将vv的迭代器反转

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> q;
        vector<vector<int>> vv;
        if(root==nullptr)
            return vv;
        int levelsize=0;
        q.push(root);
        levelsize=q.size();
        while(!q.empty())
        {
            vector<int> v;
            while(levelsize--)
        {
            TreeNode* node=q.front();
            q.pop();
            v.push_back(node->val);
            if(node->left)
                q.push(node->left);
            if(node->right)
                q.push(node->right);
        }
        vv.push_back(v);
        levelsize=q.size();
        }
        reverse(vv.begin(),vv.end());
        return vv;
    }
};
最近公共祖先

在这里插入图片描述
在这里插入图片描述
其实我们画图之后可以看到,公共祖先节点有几个很明显的特征:
如果一个节点在本节点的左子树,另一个在本节点的右子树上,那么这个节点就是那两个节点的公共祖先

如果两个节点都在一个节点的左或者右我们就用一个辅助函数来递归完成,都在左边或者右边那么两个节点之中有一个一定时他们两个节点的公共祖先
在这里插入图片描述
完整代码如下:

class Solution {
public:
//判断是否在这个树上
bool isintree(TreeNode* root,TreeNode* x)
{
    if(root==nullptr)
        return false;
    if(root==x)
        return true;
    return isintree(root->left,x)||isintree(root->right,x);
}
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if(root==p||root==q)
            return root;
        bool pinleft=isintree(root->left,p);
        bool pinright=isintree(root->right,p);
        bool qinleft=isintree(root->left,q);
        bool qinright=isintree(root->right,q);
        //一个在左一个在右
        if((pinleft&&qinright)||(pinright&&qinleft))
            return root;
        //都在左
        if(pinleft&&qinleft)
            return lowestCommonAncestor(root->left,p,q);
        //都在右
        if(pinright&&qinright)
            return lowestCommonAncestor(root->right,p,q);
        return nullptr;
    }
};
二叉树搜索树转换成排序双向链表

在这里插入图片描述
我们观察可以看到,最后排序出来的双向链表是一个有序的链表,而二叉搜索树的中序遍历一定是一个有序的序列,所以我们在这里要定义一个中序遍历的函数来用到解题

我们需要用到一个辅助的prev节点,令cur的left为prev,如果prev不为空就令prev的right为cur即可
在这里插入图片描述

class Solution {
public:
	void inorder(TreeNode* cur,TreeNode*& prev)
	{
		if(cur==nullptr)
			return;
		inorder(cur->left,prev);
		cur->left=prev;
		if(prev)
			prev->right=cur;
		prev=cur;
		inorder(cur->right,prev);
	}
    TreeNode* Convert(TreeNode* pRootOfTree) 
	{
		TreeNode* prev=nullptr;
		inorder(pRootOfTree,prev);
		TreeNode* head=pRootOfTree;
		while(head&&head->left)
		{
			head=head->left;
		}
		return head;
    }
};
前序中序还原二叉树

在这里插入图片描述
本题是根据前序和中序来构造二叉树,我们知道前序的第一个节点就是二叉树的根节点,而中序中根节点左边的就是左子树,右边为右子树,然后再遍历前序第二个节点,再次带入中序,前序的“根节点”能够将中序分为两个区间,分为区间后我们再递归两个区间
在这里插入图片描述

完整代码如下:

class Solution {
public:
    TreeNode* _buildTree(vector<int>& preorder,vector<int>& inorder,int& prei,int begin,int end)
    {
        if(begin>end)
            return nullptr;
        TreeNode* root=new TreeNode(preorder[prei]);
        int rooti=begin;
        while(rooti<=end)
        {
            if(inorder[rooti]==preorder[prei])
                break;
            else
                rooti++;
        }
        prei++;
        root->left=_buildTree(preorder,inorder,prei,begin,rooti-1);
        root->right=_buildTree(preorder,inorder,prei,rooti+1,end);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        int i=0;
        return _buildTree(preorder,inorder,i,0,inorder.size()-1);
    }
};
中序和后序还原二叉树

在这里插入图片描述
中序和后续构造二叉树就和前序和后续构造一样,转变一个思路:
但是要注意,由于后序是左右根,所以要先递归右在递归左

class Solution {
public:
    TreeNode* _buildTree(vector<int>& inorder, vector<int>& postorder,int& prei,int begin,int end)
    {
        if(begin>end)
            return nullptr;
        TreeNode* root=new TreeNode(postorder[prei]);
        int rooti=begin;
        while(rooti<=end)
        {
            if(inorder[rooti]==postorder[prei])
                break;
            else
                rooti++;
        }
        prei--;
        
        root->right=_buildTree(inorder,postorder,prei,rooti+1,end);
        root->left=_buildTree(inorder,postorder,prei,begin,rooti-1);
        
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) 
    {
        int i= postorder.size()-1;
        return _buildTree(inorder,postorder,i,0,inorder.size()-1);
    }
};

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

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

相关文章

基于 LVGL 使用 SquareLine Studio 快速设计 UI 界面

目录 简介注册与软件获取工程配置设计 UI导出源码板级验证更多内容 简介 SquareLine Studio 是一款专业的 UI 设计软件&#xff0c;它与 LVGL&#xff08;Light and Versatile Graphics Library&#xff0c;轻量级通用图形库&#xff09;紧密集成。LVGL 是一个轻量化的、开源的…

[linux][xdp] xdp 入门

xdp 全称 eXpress Data Path&#xff0c;是 linux ebpf 中的一个功能。ebpf 在内核中预留了一些插入点&#xff0c;用户可以在这些插入点插入自己的处理逻辑&#xff0c;当数据路过插入点时可以做一些预期的处理&#xff0c;具体实现方式如下&#xff1a; ① 用户编写数据处理…

【C++私房菜】序列式容器的迭代器失效问题

目录 一、list的迭代器失效 二、vector的迭代器失效 1、空间缩小操作 2、空间扩大操作 三、总结 在C中&#xff0c;当对容器进行插入或删除操作时&#xff0c;可能会导致迭代器失效的问题。所谓迭代器失效指的是&#xff0c;原先指向容器中某个元素的迭代器&#xff0c;在…

尚硅谷webpack5笔记2

Loader 原理 loader 概念 帮助 webpack 将不同类型的文件转换为 webpack 可识别的模块。 loader 执行顺序 分类pre: 前置 loadernormal: 普通 loaderinline: 内联 loaderpost: 后置 loader执行顺序4 类 loader 的执行优级为:pre > normal > inline > post 。相…

在Node.js中如何实现用户身份验证和授权

当涉及到构建安全的应用程序时&#xff0c;用户身份验证和授权是至关重要的一环。在Node.js中&#xff0c;我们可以利用一些流行的库和技术来实现这些功能&#xff0c;确保我们的应用程序具有所需的安全性。本篇博客将介绍如何在Node.js中实现用户身份验证和授权。 用户身份验…

密码学系列(四)——对称密码2

一、RC4 RC4&#xff08;Rivest Cipher 4&#xff09;是一种对称流密码算法&#xff0c;由Ron Rivest于1987年设计。它以其简单性和高速性而闻名&#xff0c;并广泛应用于网络通信和安全协议中。下面是对RC4的详细介绍&#xff1a; 密钥长度&#xff1a; RC4的密钥长度可变&am…

精品springboot相亲网站预约

《[含文档PPT源码等]精品基于springboot相亲网站[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&#xff1a;HTML5,CSS3、Ja…

在Golang中简化日志记录:提升性能和调试效率

最大化效率和有效故障排除&#xff1a;在Golang中简化日志记录 日志记录是软件开发的一个基本方面&#xff0c;有助于调试、监控和理解应用程序的流程。在Golang中&#xff0c;有效的日志记录实践可以显著提高性能并简化调试过程。本文探讨了优化Golang日志记录的技术&#xf…

常用git 打tag命令

1.查看所有tag git tag 2.创建 v5.0.0的tag git tag v5.0.0 git tag &#xff08;创建后查看&#xff09; 3.推送到远程tag git push origin v5.0.0 4.删除远程tag git push origin --delete v5.0.0 5.删除本地tag git tag -d v5.0.0 6.添加带有备注信息的tag git tag v5.…

SpringCloud认识微服务

文章目录 1.1.单体架构1.2.分布式架构1.3.微服务1.4.SpringCloud1.5.总结 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 微服务架构是一种架构模式&…

Qcom camera hal简介

目录 背景 Android相机软件框架 Qcom HAL主要包括Camx和Chi两部分 Camx中Pipeline 和 node 下图是简单模型的pipeline (sensor --> IFE --> IPE --> SinkTarget) Pipeline中的buffer管理 IFE output port的buffer在Camx中申请 IPE output port使用的buffer来自…

JavaEE进阶(7)Spring Boot 日志(概述、用途、使用:打印日志,框架介绍,SLF4J 框架介绍、更简单的日志输出)

接上次博客&#xff1a;JavaEE进阶&#xff08;6&#xff09;SpringBoot 配置文件&#xff08;作用、格式、properties配置文件说明、yml配置文件说明、验证码案例&#xff09;-CSDN博客 目录 日志概述 日志的用途 日志使用 打印日志 在程序中获取日志对象 使用日志对象…

Twing模板注入 [BJDCTF2020]Cookie is so stable1

打开题目 我们先抓包分析一下 可以输入{{7*7}}处发包试一下 可以看到在cookie处存在ssti模板注入 输入{{7*‘7’}}&#xff0c;返回49表示是 Twig 模块 输入{{7*‘7’}}&#xff0c;返回7777777表示是 Jinja2 模块 在这里可以看出是Twing模块 我们直接用固定payload就可以…

【STM32】STM32学习笔记-修改主频 睡眠模式 停止模式 待机模式(45)

00. 目录 文章目录 00. 目录01. PWR简介02. 修改主频接线图03. 修改主频相关API04. 修改主频程序示例05. 睡眠模式接线图06. 睡眠模式相关API07. 睡眠模式程序示例08. 停止模式接线图09. 停止模式相关API10. 停止模式程序示例11. 待机模式接线图12. 待机模式相关API13. 待机模式…

算法:动态规划全解(上)

一、动态规划初识 1.介绍 动态规划&#xff0c;英文&#xff1a;Dynamic Programming&#xff0c;简称DP&#xff0c;如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。所以动态规划中每一个状态一定是由上一个状态推导出来的。 例如&#xff1a;有N件物品…

Java基础八股

基础概念与常识 Java 语言有哪些特点? 简单易学&#xff1b;面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff1b;平台无关性&#xff08; Java 虚拟机实现平台无关性&#xff09;&#xff1b;支持多线程&#xff08; C 语言没有内置的多线程…

设计模式----装饰器模式

在软件开发过程中&#xff0c;有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下&#xff0c;可以动态地扩展其功能。所有这些都可以釆用装饰器模式来实现。 装饰器模式 允许向一个现有的对象添加新的功能&#xff0c;同时又不改变他的…

Window系统安装USB Redirector结合cpolar实现远程访问本地USB设备

文章目录 前言1. 安装下载软件1.1 内网安装使用USB Redirector1.2 下载安装cpolar内网穿透 2. 完成USB Redirector服务端和客户端映射连接3. 设置固定的公网地址 前言 USB Redirector是一款方便易用的USB设备共享服务应用程序&#xff0c;它提供了共享和访问本地或互联网上的U…

Docker之数据卷自定义镜像

目录 一、数据卷 ​二、自定义镜像 2.1自定义centos 一、数据卷 在docker中&#xff0c;数据卷是宿主机的一个可以供一个或多个容器使用的特殊目录&#xff0c;它可以在容器之间共享和重用&#xff0c;本地与容器间传递数据更高效&#xff1b;对数据卷的修改会立马有效&#…

08 MyBatis之查询专题(返回对象/Map/List封装Map/Map封装Map)+列名与属性名映射的三种方法

准备: INSERT INTO t_car (id, car_num, brand, guide_price, produce_time, car_type) VALUES (165, 6666, 丰田霸道, 32.00, 2020-11-11, 燃油车); INSERT INTO t_car (id, car_num, brand, guide_price, produce_time, car_type) VALUES (166, 1202, 大众速腾, 30.00, 2020…