二叉树经典OJ题(2)

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

. - 力扣(LeetCode)

class Solution {
public://前序遍历:根 左 右//左子树为空,右子树不为空的时候,不能省略左//左不为空,右子树为空的时候,可以省略右//都为空,可以省略string tree2str(TreeNode* root) { if(root==nullptr) return "";string 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;}};

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

. - 力扣(LeetCode)

思路1:

//策略1 1、如果一个在我的左子树,一个在我的右子树,那么我就是最近公共祖先//      2、如果两个走在我的左,就去左找  都不在我的左,那就去我的右找//      3、如果我自己就是,那另一个必然是我的孩子 返回我自己
class Solution {
public:bool isintree(TreeNode* root, TreeNode* x){if(root==nullptr) return false;else return root==x||isintree(root->left,x)||isintree(root->right,x);}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode*&p, TreeNode*&q){if(root==nullptr) return nullptr;if(root==p||root==q) return root;//此时就要去看看我的左子树和右子树找一找bool pleft=isintree(root->left,p);bool pright=!pleft;bool qleft=isintree(root->left,q);bool qright=!qleft;if(pleft&&qright ||qleft&&pright) return root;else if(pleft&&qleft) return lowestCommonAncestor(root->left,p,q);else return lowestCommonAncestor(root->right,p,q);}
};

思路2:

class Solution {
public://策略2:利用dfs将p和q的路径存到容器中,然后转化成链表相交的问题 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q){if(root==p||root==q) return root;stack<TreeNode*> Ppath;stack<TreeNode*> Qpath;dfs(root,p,Ppath);//找pdfs(root,q,Qpath);//找q//此时已经找到了两条目标路径,然后让长的那一条pop直到和另一条相等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();}bool dfs(TreeNode* root, TreeNode* x,stack<TreeNode*>&path){if(root==nullptr) return false;//此时可以入栈,然后去左边和右边找一下path.push(root);//无论如何都入if(root==x||dfs(root->left,x,path)||dfs(root->right,x,path)) return true;//左边或右边找到,返回true//两边都没有找到,说明root不是我们想要的,出栈并返回false;path.pop();//都没找到,就得回溯return false;}
};

三、二叉搜索树与双向链表

二叉搜索树与双向链表_牛客题霸_牛客网

class Solution {
public:void inorder(TreeNode* cur,TreeNode*&prev){if(cur==nullptr) return;//cur指向的就是中序遍历的结果inorder(cur->left,prev);//这里出现的cur就是中序的结果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;}
};

 技巧:在递归过程中,我们想要有一个变量记录全过程(该题中的prev),第一种方法就是设置成全局变量,第二种方法就是传引用。

四、前序和中序遍历序列构建二叉树

. - 力扣(LeetCode)

class Solution {
public:TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int&pi,int begin,int end) {//先创建该节点if(begin>end) return nullptr;TreeNode*root=new TreeNode(preorder[pi]);//然后根据该节点分割左右区间 在中序数组中找到树int rooti=begin;while(rooti<=end){if(inorder[rooti]==preorder[pi]) break;++rooti;}//划分区间去左子树和右子树找++pi;root->left=_buildTree(preorder,inorder,pi,begin,rooti-1);root->right=_buildTree(preorder,inorder,pi,rooti+1,end);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {//前序遍历:根 左子树 右子树    一个指针去遍历前序找根//中序遍历:左子树 根 右子树    划分左右区间//前序帮我们找根,中序帮我们划分区间int pi=0;//帮助我们按顺序遍历前序数组return _buildTree(preorder,inorder,pi,0,inorder.size()-1);}
};

五、中序和后序序列遍历构建二叉树

. - 力扣(LeetCode)

class Solution {
public:TreeNode* _buildTree(vector<int>& inorder, vector<int>& postorder,int&pi,int begin,int end){if(begin>end) return nullptr;TreeNode*root=new TreeNode(postorder[pi]);//肯定要先建立根//开始划分区间int rooti=begin;while(rooti<=end) {if(inorder[rooti]==postorder[pi]) break;++rooti;}//开始延伸,先延伸右子树,再延伸左子树--pi;root->right= _buildTree(inorder,postorder,pi,rooti+1,end);root->left= _buildTree(inorder,postorder,pi,begin,rooti-1);return root;}//后序遍历 左子树 右子树 根//中序遍历 左子树 根 右子树//后序遍历帮我们找根。   中序遍历帮我们划分左右区间TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder){int n=inorder.size();int pi=n-1;return _buildTree(inorder,postorder,pi,0,n-1);}
};

六、非递归实现二叉树的前序遍历

. - 力扣(LeetCode)

class Solution {
public://根 左子树 右子树//根、左子树、然后再栈里面搞右子树vector<int> preorderTraversal(TreeNode* root) {stack<TreeNode*> st;vector<int> ret;if(root==nullptr) return ret;TreeNode*cur=root;//1、访问左路节点//2、访问左路节点的右子树while(!st.empty()||cur) //cur不为空表示当前的树还没访问,栈不为空表示还有右子树没有访问{while(cur){ret.push_back(cur->val);st.push(cur);cur=cur->left;}//开始去访问右子树TreeNode* t=st.top();st.pop();//转化成子问题,去访问节点的右树cur=t->right;}return ret;}
};

七、非递归实现二叉树的中序遍历

. - 力扣(LeetCode)

class Solution {
public:
//中序  左子树 根 右子树 
//1 左路节点
//2 左子树的右路节点
//从栈里取到左路节点,意味着左路节点,以为着这个节点的左子树已经访问完了。
// 非递归实现 vector<int> inorderTraversal(TreeNode* root) {stack<TreeNode*> st;vector<int> ret;if(root==nullptr) return ret;TreeNode*cur=root;while(cur||!st.empty()){while(cur){st.push(cur);cur=cur->left;}//此时,从栈中拿出来TreeNode* t=st.top();st.pop();ret.push_back(t->val);cur=t->right;}return ret;}
};

八、非递归实现二叉树的后序遍历

. - 力扣(LeetCode)

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) { stack<TreeNode*> st;vector<int> ret;if(root==nullptr) return ret;TreeNode*cur=root;//1、访问左路节点//2、访问左路节点的右子树TreeNode*prev=nullptr;while(!st.empty()||cur) //cur不为空表示当前的树还没访问,栈不为空表示还有右子树没有访问{while(cur){st.push(cur);cur=cur->left;}//开始去访问右子树TreeNode* t=st.top();if(t->right==nullptr||t->right==prev){ret.push_back(t->val);st.pop();prev=t;}//从栈中弹出的节点,我们只能确定其左子树肯定访问完了,但是无法确定右子树是否访问过。else cur=t->right;}return ret;}
};

     还有一种思路就是,因为我们的结果是存在一个数组去返回的,因此我们可以按照前序遍历的逻辑:将问题拆分成 右路节点和右路节点的左子树。然后按照 根、右子树、左子树的顺序去访问(和后序相反),最后再逆置我们的返回数组即可。这是一种取巧的方法,但是能成功是因为该题是将结果放到一个数组中返回的,如果该题是要求我们边遍历边访问,比如打印,那么该方法就不可行。

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {stack<TreeNode*> st;vector<int> ret;if(root==nullptr) return ret;TreeNode*cur=root;//1、访问右路节点//2、访问右路节点的左子树while(!st.empty()||cur) //cur不为空表示当前的树还没访问,栈不为空表示还有左子树没有访问{while(cur){ret.push_back(cur->val);st.push(cur);cur=cur->right;}//开始去访问左子树TreeNode* t=st.top();st.pop();//转化成子问题,去访问节点的右树cur=t->left;}reverse(ret.begin(),ret.end());return ret;}
};

 九、小总结

1、二叉搜索树涉及到升序的情况,一般是根中序遍历建立联系

2、前序和中序构建二叉树,以及中序和后序构建二叉树,本质上是利用一个序列找根,另一个序列去划分问题。同时我们会发现其实后序遍历如果反着来的话大多数情况下可以转化成类似前序遍历,比如4、5题和7、8题,都可以用前序遍历的思路去解决后序遍历。

3、非递归实现二叉树的前中后序遍历,本质上是将问题拆分为1、访问左路节点 2、访问左路节点的右子树。需要用一个辅助栈去帮助我们记录节点。

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

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

相关文章

Java基于微信小程序的校园外卖平台设计与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

使用Python爬虫代理IP快速增加博客阅读量

目录 前言 二、Python爬虫代理IP技术简介 1.什么是爬虫&#xff1f; 2.什么是代理IP&#xff1f; 3.为什么使用代理IP&#xff1f; 三、使用Python爬虫代理IP增加博客阅读量的步骤 1.获取代理IP地址 2.模拟多次访问 3.定时任务 四、注意事项 五、总结 前言 随着互联…

Matlab 2024安装教程(附免费安装包资源)

鼠标右击软件压缩包&#xff0c;选择“解压到MatlabR2024a“。 2.打开解压后的文件夹&#xff0c;鼠标右击“MATHWORKS_R2024A“选择装载。 鼠标右击“setup“选择”以管理员身份运行“。点击“是“&#xff0c;然后点击”下一步“。复制一下密钥粘贴至输入栏&#xff0c;然后…

【Tars-go】腾讯微服务框架学习使用01--初始化服务

1 初始INIT-Demo运行 按照官网描述 go get 安装框架依赖 # < go 1.16 go get -u github.com/TarsCloud/TarsGo/tars/tools/tarsgo go get -u github.com/TarsCloud/TarsGo/tars/tools/tars2go # > go 1.16 go install github.com/TarsCloud/TarsGo/tars/tools/tarsgolat…

SSH安全设置

今天发现自己的公有云服务器被攻击了 然后查看了登录日志&#xff0c;如上图 ls -sh /var/log/secure vim /var/log/secure然后增加了安全相关的设置 具体可以从以下方面增加安全性&#xff1a; 修改默认SSH端口公有云修改安全组策略及防火墙端口设置登录失败次数锁定用户及限…

MySQL事务与事务原理

目录 事务 事务的四大特性ACID 事务隔离级别 事务原理 存储引擎 四大特性的保证 MVCC 事务链 ReadView 事务 事务指逻辑上的一组操作&#xff0c;组成这组操作的各个单元&#xff0c;要么全部成功&#xff0c;要么全部失败。 start transaction; -- 开启事务 或者 b…

B端:设置页面如何减少用户的录入操作。

录入操作尤其是文字录入是比较是比较繁琐的&#xff0c;尤其是在移动端小屏幕上&#xff0c;简直就是灾难。不过我们可以通过合理的设置、识别、记忆、自动填充等技术来有效的减少录入。 在 B 端设置页面中&#xff0c;可以采取多种方式来减少用户的录入操作&#xff0c;提高用…

第二期书生浦语大模型训练营第三次作业

任务一&#xff1a;在茴香豆 Web 版中创建自己领域的知识问答助手 构建个人回答助手 进入web页面&#xff0c;传输属于自己的文件&#xff0c;此处进行输入大量投资领域资料&#xff0c;构建个人投资者问答助手 回答示例 茴香豆缺陷 此处会发现茴香豆仍然存在一些缺点&#…

一、基础算法-快速排序

1.快速排序 快速排序主要利用了分治的思想&#xff0c;具体步骤为&#xff1a; step1 确定分界点&#xff0c;常用为q[left],q[right],q[mid]&#xff0c;也可以是随机的 step2 调整区间&#xff0c;将比分界点小的放左边&#xff0c;大的放右边 step3 利用递归处理左右两端 …

Web攻防10_PHP反序列化_概念魔术方法POP链构造

文章目录 1、什么是反序列化操作&#xff1f; - 类型转换2、常见PHP魔术方法- 对象逻辑魔术方法概念常见魔术方法魔术方法与反序列化漏洞 3、反序列化安全漏洞原理&#xff1a;漏洞探针漏洞危害 4、反序列化漏洞利用- POP链构造反序列化常见起点反序列化常见跳板反序列化常见终…

LeetCode 19. 删除链表的倒数第 N 个结点

LeetCode 19. 删除链表的倒数第 N 个结点 1、题目 力扣题目链接&#xff1a;19. 删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a; head [1,2,3,4,5], n 2 输出&am…

LeetCode 678——有效的括号字符串

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 需要两个栈&#xff0c;一个用来保存左括号所在的位置索引&#xff0c;一个用来保存星号所在的位置索引。 从左往右遍历字符串&#xff0c;如果是左括号或者星号&#xff0c;则将位置索引分别入栈&#xff0c;如…

ELK——日志处理界的瑞士军刀

目录 引言 一、ELK简介 &#xff08;一&#xff09;基本概述 1.Elasticsearch服务 2.Logstash服务 2.2 logstash关键组件 2.2 logstash数据流向 3.Kibana服务 &#xff08;二&#xff09;ELK工作流程 &#xff08;三&#xff09;ELK的应用价值 二、部署搭建ELK &…

【Web】NSSRound#1-20 Basic 刷题记录(全)

目录 [NSSRound#1 Basic]basic_check [NSSRound#1 Basic]sql_by_sql [NSSCTF 2nd]php签到 [NSSCTF 2nd]MyBox [NSSCTF 2nd]MyBox(revenge) [NSSCTF 2nd]MyHurricane [NSSCTF 2nd]MyJs [NSSRound#3 Team]This1sMysql [NSSRound#3 Team]path_by_path [NSSRound#…

【入门】时钟旋转

时间限制 : 1 秒 内存限制 : 128 MB 时钟上面的时针从m时走到n时旋转了多少度&#xff1f;&#xff08;m<n&#xff0c;且m和n都是1~12之间的整数&#xff09; 输入 2个整数m和n 输出 一个整数代表时针旋转的度数 样例 输入 1 4 输出 90 提示 基础问题 #includ…

SQL语法 case when语句用法讲解

CASE WHEN解释 &#xff1a; SQL中的CASE WHEN语句是一种条件表达式&#xff0c;它允许你根据不同的情况返回不同的值。CASE WHEN通常用于SELECT语句中&#xff0c;用于创建新的列&#xff0c;该列的值取决于其他列的值。CASE WHEN可以用于任何可以使用表达式的地方。 大致概…

二叉树和数据结构

小红的完全二叉树构造 题目描述 小红想构造一个总共 n 个节点完全二叉树&#xff0c;该二叉树满足以下两个性质&#xff1a; 1. 所有节点的权值值为 1 ~ n 的一个排列。 2. 除了根节点以外&#xff0c;每个节点的权值和它父亲的权值的乘积为偶数。 请你帮小红构造出这个二叉树…

K8S一 k8s基础知识及实战

一 K8S 概览 1.1 K8S 是什么&#xff1f; K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ K8S 是Kubernetes的全称&#xff0c;源于希腊语&#xff0c;意为“舵手”或“飞行员”&#xff0c;官方称其是&#xff1a;用于自动部署、扩展和管理“容器化&#xff08…

软考 系统架构设计师系列知识点之大数据设计理论与实践(5)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之大数据设计理论与实践&#xff08;4&#xff09; 所属章节&#xff1a; 第19章. 大数据架构设计理论与实践 第3节 Lambda架构 19.3.1 Lambda架构对大数据处理系统的理解 Lambda架构由Storm的作者Nathan Marz提出&…

伺服系统中电机磁极偏角自学习的实现方案

一、 电机磁极偏角自学习原理简述 要知道磁极偏角&#xff0c;首先要明确的是磁极角&#xff0c;在我个人的理解里磁极角就是park和Ipark变换里所需的电角度&#xff0c;我们的矢量控制方法是定磁链的&#xff0c;就是要保证两相同步旋转坐标系的Id轴和三相静止坐标系的A轴要重…