C++ 二叉树OJ题

💓博主CSDN主页:麻辣韭菜-CSDN博客💓

⏩专栏分类:C++知识分享⏪

🚚代码仓库:C++高阶🚚

🌹关注我🫵带你学习更多C++知识
  🔝🔝

前言

C++二叉搜索树 这篇讲解了搜索二叉树的实现的,本篇从实战出发,让大家更好的掌握和理解二叉树的!!!!



1. 二叉树创建字符串。606. 根据二叉树创建字符串 - 力扣(LeetCode)

 

找出规律,我们就好办了 直接代码演示。 

class Solution {
public:
    string tree2str(TreeNode* root) {
        if(root == nullptr) //根为空 直接返回空串!
         return "";
         string str  = to_string(root->val); //外面解释这个函数
         //结合 刚才的3点总结 左右都为空不加括号,左为空是要加括号的。 
         if(root->left || root->right)
         {
            str += '(';
            str += tree2str(root->left);
            str += ')';
         }
        if(root->right)
        {
            str += '(';
            str += tree2str(root->right);
            str += ')';
        }
        return str;
    }
};

 to_string 是 C++ 标准库中的一个函数,它定义在 <string> 头文件中。这个函数用于将一个数值类型(如 intdouble 等)转换为其对应的字符串表示形式。 在给出的代码片段中,to_string(root->val) 被用来将 TreeNode 对象的 val 属性(假设是一个数值类型)转换为一个字符串。这样,就可以将该字符串与其他部分拼接起来,形成最终的树形结构字符串表示。 例如,如果 root->val 是整数 3,那么 to_string(root->val) 将返回字符串 "3"。 简而言之,to_string 函数在 C++ 中用于数值到字符串的转换。在你的代码中,它被用来将树节点的值转换为字符串,以便构建树结构的字符串表示。

这里有点难理解是左不为空,右为空。按照上面条件不是就错了吗?

我们按照题的要求前序遍历,是先根在左然后右 看递归展开图  

 

递归是一层一层展开,如果左不为空,右为空它们就会像上图那样一直找到左为空为止,

这时在递归右子树 。

 


2. 二叉树的分层遍历1。102. 二叉树的层序遍历 - 力扣(LeetCode)

解题思路 :我们创建一个队列,前序遍历这个数组,每遍历一次,就进队列一次,

根据队列的性质先进先出。就解决了!!! 

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode* > q; //创建队列
        int levelSize = 0; //层数变量
        vector<vector<int>> vv;
        if(root) //节点不为空进队列
        {
            q.push(root);
            levelSize = 1; //为什么是1 根就只有一个。
        }
        while(!q.empty()) //如果队列不为空
        {
            vector<int> v;
            while(levelSize)
            {
                TreeNode* front = q.front();
                q.pop();//出队列
                v.push_back(front->val); //把队顶的数据压进顺序表V
                //带入下一层
                if(front->left)
                    q.push(front->left);
                if(front->right)
                    q.push(front->right);
               --levelSize;
            }
            vv.push_back(v); //把每一层出完,压进二维的顺序表
            levelSize = q.size();//更新每一层,数据有多少个。
           
        }

        
        return vv;
    }
};

 


3. 二叉树的分层遍历2。107. 二叉树的层序遍历 II - 力扣(LeetCode)

这个题没什么好说的,来个投机的,把第二题逆置再返回。 

 

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode* > q; //创建队列
        int levelSize = 0; //层数变量
        vector<vector<int>> vv;
        if(root) //节点不为空进队列
        {
            q.push(root);
            levelSize = 1; //为什么是1 根就只有一个。
        }
        while(!q.empty()) //如果队列不为空
        {
            vector<int> v;
            while(levelSize)
            {
                TreeNode* front = q.front();
                q.pop();//出队列
                v.push_back(front->val); //把队顶的数据压进顺序表V
                //带入下一层
                if(front->left)
                    q.push(front->left);
                if(front->right)
                    q.push(front->right);
               --levelSize;
            }
            vv.push_back(v); //把每一层出完,压进二维的顺序表
            levelSize = q.size();//更新每一层,数据有多少个。
           
        }

        reverse(vv.begin(),vv.end()); //用迭代器逆置
        return vv;
    
    }
    
};

 

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

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

 

解题思路 根据解释,我们可以得出 一个在我的左子树,一个在我的右子树。我就是公共祖先。那我们可以用路径相交思路来解决,比如7和0的公共祖先。根据递归深度路径大小,

让深度更深的那个先走,等它们深度一样时,同时再走,最后相等的那个值就是公共祖先。

class Solution {
public:
    bool GetPath(TreeNode* root,TreeNode* x,stack<TreeNode*>& path)
    {
        if(root == nullptr) //根都为空了 还找个屁
        {
            return false;
        }
        //不为空进栈
        path.push(root);
        if(root == x) // 找到了
        {
            return true;
        }
        if(GetPath(root->left,x,path)) //左递归
        {
            return true;
        }
        if(GetPath(root->right,x,path))//右递归
        {
            return true;
        }
        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(qPath.size() != pPath.size())
        {
            if(qPath.size()>pPath.size())
            qPath.pop();
            else
            pPath.pop();
        }
        while(qPath.top() != pPath.top())
        {
            qPath.pop();
            pPath.pop();
        }

    
        return qPath.top();
        
    }
};

 


 

5. 二叉树搜索树转换成排序双向链表。二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com)

解题思路:中序遍历,然后 改链接方向,如何改?根的左就是prev。 右怎么改?记录父亲节点,根的右就是父亲节点  以4举例:4的左为空,那它连接就是nullptr,再看右为空返回上一层这时父亲连接它的右 

class Solution {
public:
	 void InorderConvert(TreeNode* cur, TreeNode*& prev)
	 {
		if(cur == nullptr)
			return ;
		InorderConvert(cur->left,prev);
		cur->left = prev;
		if(prev)
			prev->right = cur;
		prev = cur;
		InorderConvert(cur->right,prev);
	 }
    TreeNode* Convert(TreeNode* pRootOfTree)
	 {

		TreeNode* prev = nullptr;

        InorderConvert(pRootOfTree,prev);
		TreeNode* head = pRootOfTree;
		while (head && head->left) 
		{
			head = head->left;
		}
		return head;
    }
	
};

 

 


6. 根据一棵树的前序遍历与中序遍历构造二叉树。 105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

 解题思路:前序确定什么? 确定根, 中序确定什么? 确定根的左右区间 

class Solution {
public:
    TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder, int& prei, int inbegin, int inend)
    {
        if(inbegin > inend)
        {
            return nullptr;
        }
        TreeNode* root = new TreeNode(preorder[prei]);
        int rooti = inbegin;
        //分割区间
        while(rooti< inend)
        {
            if(inorder[rooti] == preorder[prei])
            {
                break;
            }
            else
                rooti++;
        }
        ++prei;
        // 区间[inbegin, rooti-1] prei [rooti+1,inend] 
        //转化成子问题
        root->left = _buildTree(preorder,inorder,prei,inbegin,rooti-1);
        root->right = _buildTree(preorder,inorder,prei,rooti+1,inend);
        return root;

    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        int i = 0;
        return _buildTree(preorder, inorder, i, 0, inorder.size()-1);

    }
};

 


7. 根据一棵树的中序遍历与后序遍历构造二叉树。106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

  解题思路:还是一样,中序确定根的左右区间,后序确定根。先创建右再创建左

 

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

    }
};

​

 


8. 二叉树的前序遍历,非递归迭代实现 144. 二叉树的前序遍历 - 力扣(LeetCode)

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) 
    {
        //迭代用栈 
        stack<TreeNode*> s;
        vector<int> v;
        TreeNode* cur = root;
        while(cur || !s.empty())
        {
            //开始访问
            while(cur)
            v.push_back(cur->val);
            s.push(cur)
            cur = cur->left;
        }
        //访问右树
        TreeNode* top = s.top();
        s.pop();
        cur = top->right;
    }
    return v;
};

 

 


9. 二叉树中序遍历 ,非递归迭代实现。94. 二叉树的中序遍历 - 力扣(LeetCode)

解题思路:和前序不同的是 先访问左 再访问根 然后右。那这样的话 一直迭代到左树为空为止,然后取栈中取元素 push到vector中,最后访问右树。

 

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) 
    {
        vector<int> v;
        stack<TreeNode*> s;
        TreeNode* cur = root;
        while(cur || !s.empty())
        {
            while(cur)
            {
                s.push(cur);
                cur = cur->left;
            }
            TreeNode* top = s.top();
            s.pop();
            v.push_back(top->val);
            cur = top->right;
        }
        return v;
    }
};

 


10. 二叉树的后序遍历 ,非递归迭代实现。145. 二叉树的后序遍历 - 力扣(LeetCode)

 

解题思路:后序 先左再右然后根  右为空了再取栈顶的元素,这里不一样的是 如果左右都不空 怎么访问根? 看下图

 

从这个图可以说明 上一个访问的节点如果等于我的右子树的根,那我不就是根吗? 

 

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root)
    {
         vector<int> v;
        stack<TreeNode*> s;
        TreeNode* cur = root;
        TreeNode* prev = nullptr;
        while(cur || !s.empty())
        {
            while(cur)
            {
                s.push(cur);
                cur = cur->left;
            }
            TreeNode* top = s.top();
            if(top->right == nullptr || top->right == prev)
            {   v.push_back(top->val);
                s.pop();
                prev = top;
            }
            else
                cur = top->right;
        }
        return v;
    }
    
};

 

下节预告 map和set 关注我 带你学习更多C++知识!!!! 

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

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

相关文章

动态规划1

动态规划问题的五步操作&#xff1a; 动态规划就是把dp表填满&#xff0c;则最终一定有一个数据是我们所需要的数据 下面以一道简单的题目进行讲解 本题其实就是斐波那契数列的一个plus版 &#xff0c;就是利用递推关系求值的过程 1.前期准备&#xff1a;创建dp表(使用一维…

GRE和MGRE

思维导图 综合实验 配置IP地址 R1&#xff1a; [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip add 192.168.1.1 24 [R1-GigabitEthernet0/0/0]int s3/0/0 [R1-Serial3/0/0]ip add 15.1.1.1 24 R2: [R2]int g 0/0/0 [R2-GigabitEthernet0/0/0]ip ad 192.168.2.2 24 [R2-G…

基于四足机器人和机械臂的运动控制系统(二)

文章目录 前言一、四足步态二、视觉抓取三、远程遥控 谢绝转载&#xff0c;无作者许可不可用做其他用途&#xff08;如教育展示产品、课程设计或毕业设计等&#xff09; 前言 衔接上一篇文章&#xff0c;这篇文章主要来介绍项目的初步实现 一、四足步态 可以知道&#xff0…

常用的几种排序算法小结

目录 1.冒泡排序 2.堆排序 2.1堆的基础知识和特性 2.2向上调整算法和向下调整算法 2.3堆排序实现 3.插入排序 4.希尔排序 5.选择排序 5.1选择排序递归版 5.2选择排序非递归版 6.快速排序 6.1 Hoare版本之递归 6.1.1普通版 6.1.2随机数版 6.1.3三数取中版 6.1.4小区间优化…

前端虚拟滚动列表 vue虚拟列表

前端虚拟滚动列表 在大型的企业级项目中经常要渲染大量的数据&#xff0c;这种长列表是一个很普遍的场景&#xff0c;当列表内容越来越多就会导致页面滑动卡顿、白屏、数据渲染较慢的问题&#xff1b;大数据量列表性能优化&#xff0c;减少真实dom的渲染 看图&#xff1a;绿色…

安装最新的wxPython和Python3并保证二者兼容

要安装最新的wxPython和Python3并保证二者兼容&#xff0c;你可以按照以下步骤进行操作&#xff1a; 安装Python3&#xff1a; 访问Python官方网站下载适合你操作系统的最新版Python3安装包。运行安装程序&#xff0c;确保在安装过程中将Python添加到系统环境变量中。安装完成…

【Java】:static成员和代码块

目录 1.static成员 1.1再谈学生类 1.2static修饰成员变量 1.3static修饰成员方法 1.4static成员变量初始化 1.4.1就地初始化 1.4.2静态代码块初始化 2.代码块 2.1代码块概念以及分类 2.2普通代码块 2.3构造代码块 2.4静态代码块 1.static成员 1.1再谈学生类 使用类…

MATLAB 点云随机渲染赋色(51)

MATLAB 点云随机渲染赋色(51) 一、算法介绍二、算法实现1.代码2.效果总结一、算法介绍 为点云中的每个点随机赋予一种颜色,步骤和效果如图: 1、读取点云 (ply格式) 2、随机为每个点的RGB颜色字段赋值 3、保存结果 (ply格式) 二、算法实现 1.代码 代码如下(示例):…

gin基础学习笔记--参数验证

用gin框架的数据验证&#xff0c;可以不用解析数据&#xff0c;减少if else&#xff0c;会简洁许多。 package mainimport ("fmt""time""github.com/gin-gonic/gin""github.com/gorilla/sessions" )// 初始化一个cookie存储对象 // s…

基于STM32的武警哨位联动报警系统设计,支持以太网和WIFI通信

1.功能 本文提出的武警报警信息系统终端&#xff0c;可实现报警和联动响应&#xff0c;支持以太网和WIFI两种通信模式&#xff0c;可实现移动哨位报警和固定哨位报警&#xff0c;语音和显示报警信息用户可自行定制。 本终端主要由STM32F103处理器模块和C8051F340处理器模块构…

P-MapNet:Far-seeing Map Generator Enhanced by both SDMap and HDMap Priors

主页&#xff1a;homepage 参考代码&#xff1a;P-MapNet 动机与出发点 在感知系统中引入先验信息是可以提升静态元素感知网络的上限的&#xff0c;这篇文章对SD地图采用栅格化表示&#xff08;也就是图像形式&#xff09;&#xff0c;之后用CNN网络去抽取栅格化SD地图的信息&…

linux ubuntu 在保存文件不被允许,但是root权限

现象&#xff1a;MobaXterm_Personal_2登录到服务器&#xff0c;切换到root用户&#xff0c;然后使用MobaXterm_Personal_2自带的编辑器&#xff0c;编写文件&#xff0c;进行保存不被允许&#xff1b;查看目录root是有权限进行修改文件的&#xff0c;然后使用vim进行修改保存&…

网络安全-内网渗透2

一、MIC 将我们上次未描述完的MIC在这里详细解释一下 咱们所抓的第二个包会给返回一个服务端的challenge 之后服务器回包的第三个包会回复一个client challenge 所以咱们客户端和服务端现在分别有两个challenge&#xff0c;相当于客户端和服务端互相交换了一下challenge 因此…

本地搭建多人协作ONLYOFFICE文档服务器并结合Cpolar内网穿透实现公网访问远程办公

文章目录 1. 安装Docker2. 本地安装部署ONLYOFFICE3. 安装cpolar内网穿透4. 固定OnlyOffice公网地址 本篇文章讲解如何使用Docker在本地服务器上安装ONLYOFFICE&#xff0c;并结合cpolar内网穿透实现公网访问。 Community Edition允许您在本地服务器上安装ONLYOFFICE文档&…

高精度(大整数)

本文用于记录个人算法竞赛学习&#xff0c;仅供参考 一.什么是大整数 当一个数的位数已经很大了&#xff08;比如有10^6&#xff09;&#xff0c;常规的数据类型已经存不下了&#xff0c;那么这个时候就可以用数组来存&#xff0c;数组的每个元素代表数的每一位&#xff0c;且…

Base64编码的全面介绍

title: Base64编码的全面介绍 date: 2024/3/31 18:55:49 updated: 2024/3/31 18:55:49 tags: Base64编码网络传输文本转换数据膨胀非加密性质应用场景安全传输 1. Base64的定义和作用 Base64是一种用64个字符表示二进制数据的编码方式&#xff0c;通常用于在网络传输中将二进…

什么是Redis数据一致性?如何解决?

在系统中缓存最常用的策略是&#xff1a;服务端需要同时维护DB和cache&#xff0c;并且是以DB的结果为准–Cache-Aside Pattern&#xff08;缓存分离模式、旁路缓存&#xff09; 读数据 单纯的读数据是不会产生数据不一致&#xff0c;只有并发下读和写才会存在数据不一致。 写…

安装即启动?探索流氓App的自启动“黑科技” (Android系统内鬼之ContentProvider篇)

前段时间发现了一个神奇的app&#xff0c;它居然可以在安装之后立即自启动&#xff1a; 看到没有&#xff0c;在提示安装成功大概1到2秒后&#xff0c;就直接弹出Toast和通知了&#xff01; 好神奇啊&#xff0c;在没有第三方app帮忙唤醒的前提下&#xff0c;它是怎么做到首次安…

2024年 前端JavaScript 进阶 第2天 笔记

2.1-内容和创建对象方式 2.2-164-构造函数 2.3-new实例化执行过程 2.4-实例成员和静态成员 2.5-基本包装类型 2.6-0bject静态方法 2.7-数组reduce累计方法 对象数组 加0 2.7-数组find、every和转换为真 --说明手册文档 MDN Web Docs 2.8-字符串常见方法 2.3 String 1.常见实例…

【yolo检测】基于YOLOv8与DeepSORT实现多目标跟踪

1.配置环境 conda版本23.5.0 创建虚拟环境&#xff0c;Python版本选择3.10&#xff0c;环境命名为yolov8 conda create --name yolov8 python3.10进入环境 conda activate yolov82.安装工具包 实测网络问题可以用手机热点或者加-i镜像解决。 pip install -r requirements.t…