二叉树经典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;…

SpringBoot 封装Http请求

1.引入jar包 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.10</version></dependency> 2.HttpUtils操作类封装 package com.gnss.gis.utils;import com.gnss…

MySQL 知识目录

MySQL 知识相关目录主要参考尚硅谷 宋红康老师的视屏&#xff0c;参考链接为 尚硅谷MySQL入门到高级-宋红康版_哔哩哔哩_bilibili 1、基础篇 数据库概述 链接&#xff1a;数据库概述-CSDN博客基本的select语句 链接&#xff1a;基本的select语句-CSDN博客mysql 运算符 链接&a…

一文读懂Vue中的el-dialog(附Demo)

目录 前言1. 基本知识2. Demo 前言 原先对于该知识点写过一个Demo&#xff0c;推荐阅读&#xff1a;点击按钮框来选择相应信息&#xff08;Vue Java&#xff09; 1. 基本知识 el-dialog 是 Element UI 框架中的一个组件&#xff0c;用于创建对话框 提供了丰富的功能和选项…

Day8-Python基础学习之地图和柱状图构建

构建地图 # 地图可视化基本使用 from pyecharts.charts import Map from pyecharts.options import * ​ # 准备地图对象 map Map() # 准备数据 data [("北京市", 99),("上海市", 199),("湖南省", 299),("台湾省", 399),("广东…

积分学<4>——定积分的性质

索引 定积分的性质远算性质定理4.1 定积分的线性性定理4.2 定积分的乘积可积性定理4.3 定积分的保序性定理4.4 定积分的绝对可积性定理4.5 定积分的区间可加性 积分中值定理积分第一中值定理 定积分的性质 远算性质 定理4.1 定积分的线性性 若函数 f ( x ) f\left ( x \righ…

Leetcode 3117. Minimum Sum of Values by Dividing Array

Leetcode 3117. Minimum Sum of Values by Dividing Array 1. 解题思路2. 代码实现 题目链接&#xff1a;3117. Minimum Sum of Values by Dividing Array 1. 解题思路 这一题思路上就是一个动态规划&#xff0c;我们只需要考察每一个元素是否需要放在当前的group当中还是作…

使用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;提高用…

MacOS Python版本管理(pyenv)

1. 通过 homebrew 安装 pyenv brew update brew install pyenv 2. 修改 zsh profile 否则通过pyenv切换python版本会不生效 # 编辑 .zshrc or ~/.bash_profile vim ~/.zshrc# 在配置下面增加 export PYENV_ROOT"$HOME/.pyenv" export PATH"$PYENV_ROOT/shi…

python__构造方法

魔术方法 1、__init__()方法&#xff0c;被称为构造方法&#xff0c;在创建类对象时&#xff0c;会自动执行&#xff0c;在创建类对象的时候&#xff0c;会将传入的参数自动传递给__init__()方法。 class Student:name Noneage Nonetel Nonedef __init__(self,name,age,te…

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

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

长短期记忆网络 – Long short-term memory | LSTM

目录 简单的例子理解LSTM LSTM的输入和输出信息。 隐状态和细胞状态是什么

一、基础算法-快速排序

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

ubuntu下利用ffmpeg工具将视频帧推流至rtsp

1、win10安装播放器 推荐安装 PotPlayer 64 bit。此播放器可以打开推流链接进行播放。 2、安装ffmpeg 建议在python环境中安装&#xff1a; 2.1、pip换清华源pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip config set global.trusted-hos…

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

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