二叉树经典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.hqwc.cn/news/619512.html

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

相关文章

Zynq7000中的应用处理单元(APU)介绍

Zynq 7000 系列基于 AMD 的 SoC 架构。这些产品将功能丰富的双核或单核处理系统&#xff08;PS&#xff09;和 AMD 可编程逻辑&#xff08;PL&#xff09;集成在单个设备中&#xff0c;这些处理器是 Arm Cortex-A9 处理器&#xff0c;配备 NEON 协处理器&#xff0c;以多处理器…

2024蓝桥A组A题

艺术与篮球&#xff08;蓝桥&#xff09; 问题描述格式输入格式输出评测用例规模与约定解析参考程序难度等级 问题描述 格式输入 无 格式输出 一个整数 评测用例规模与约定 无 解析 模拟就好从20000101-20240413每一天计算笔画数是否大于50然后天数&#xff1b; 记得判断平…

每日一VUE——组件的生命周期

文章目录 VUE组件的生命周期生命周期钩子函数实例创建Teleport VUE组件的生命周期 组件生命周期 组件从创建到挂载、更新、到销毁的一系列过程被称为组件的生命周期。 生命周期函数 在组件的各个生命周期节点执行的函数&#xff0c;为生命周期钩子函数。 生命周期钩子函数…

如何在Rust中操作JSON

❝ 越努力&#xff0c;越幸运 ❞ 大家好&#xff0c;我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder。 前言 我们之前在Rust 赋能前端-开发一款属于你的前端脚手架中有过在Rust项目中如何操作JSON。 由于文章篇幅的原因&#xff0c;我们就没详细介绍…

Web 题记

[极客大挑战 2019]LoveSQL 看到这种就肯定先想到万能密码&#xff0c;试试&#xff0c;得到了用户名和密码 总结了一些万能密码&#xff1a; or 11 oror admin admin-- admin or 44-- admin or 11-- admin888 "or "a""a admin or 22# a having 11# a havin…

基于ArcGIS、InVEST与RUSLE水土流失模拟及分析

我国是世界上水土流失最为严重的国家之一&#xff0c;水土流失面广量大。据第一次全国水利普查成果&#xff0c;我国现有水土流失面积294.91万平方公里。严重的水土流失&#xff0c;是我国生态恶化的集中反映&#xff0c;威胁国家生态安全、饮水安全、防洪安全和粮食安全&#…

Stable Diffusion之文生图模型训练

1、数据准备 提前准备好一组相关的照片。 在线的图片处理网站 BIRME - Bulk Image Resizing Made Easy 2.0 (Online & Free) 将图片转成统一大小&#xff0c;支持批量处理&#xff0c;效率高 2、生成提示词 进入stable diffusion webui页面 旧版直接使用 train/proproc…

(四)C++自制植物大战僵尸游戏启动流程

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/ErelL 一、启动方式 鼠标左键单机VS2022上方工具栏中绿色三角按钮&#xff08;本地Windows调试器&#xff09;进行项目启动。第一次启动项目需要编译项目中所有代码文件&#xff0c;编译生成需要一定的时间。不同性能的电…

AliyunCTF 2024 - BadApple

文章目录 前言环境搭建漏洞分析漏洞利用参考 前言 本文首发于看雪论坛 https://bbs.kanxue.com/thread-281291.htm 依稀记得那晚被阿里CTF支配的恐惧&#xff0c;今年的阿里CTF笔者就做了一道签到PWN题&#xff0c;当时也是下定决心要学习 jsc pwn 然后复现这道 BadApple 题目…

小米温度计接入HA后,手机米家app里温度计就看不到温度数值了

环境&#xff1a; 小米温度计 HA OS Core 2023.12.1 Supervisor 2024.04.0 Operating System 11.1 问题描述&#xff1a; 小米温度计接入HA后&#xff0c;手机米家app里和HA里面温度计就看不到温度数值了 解决方案&#xff1a; 1.前往米家APP&#xff0c;解绑温度计和本地…

粮油包装生产线效率与品质双提升攻略

随着生活节奏的加快和消费者对食品安全、便捷性要求的提高&#xff0c;粮油包装生产线的效率与产品质量成为了决定企业竞争力的重要因素。那么&#xff0c;如何在保证产品质量的同时&#xff0c;提升粮油包装生产线的生产效率呢?星派将为您揭示答案。 一、引入智能化设备&…

简单了解C++常见编程问题解决方案

这篇文章主要介绍了C常见编程问题解决方案,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 电脑配置&#xff1a;window10, 64位操作系统&#xff0c;基于x64的处理器&#xff0c;Microsoft Visual Studio Comm…