当前位置: 首页 > news >正文

牛客101:二叉树

目录

一、二叉树前序遍历

二、二叉树中序遍历

三、二叉树后序遍历

四、二叉树层序遍历

五、按之字形顺序打印二叉树

六、二叉树最大深度

七、二叉树中和为某一值的路径(一)

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

九、对称的二叉树

十、合并二叉树

十一、二叉树的镜像

十二、判断是不是二叉搜索树

十三、判断是不是完全二叉树

十四、判断是不是平衡二叉树

十五、二叉搜索树的最近公共祖先

十六、在二叉树中找到两个节点的最近公共祖先

十七、序列化二叉树

十八、重建二叉树

十九、输出二叉树的右视图


二叉树的三种遍历其实都可以借助栈来做,因为递归过程就像是入栈出栈过程

一、二叉树前序遍历

二叉树的前序遍历_牛客题霸_牛客网

    void preorder(vector<int>&res,TreeNode* root){if(!root)return;res.push_back(root->val);preorder(res, root->left);preorder(res, root->right);}vector<int> preorderTraversal(TreeNode* root) {vector<int> ret;preorder(ret,root);return ret;}

二、二叉树中序遍历

二叉树的中序遍历_牛客题霸_牛客网

    void inorder(vector<int>& ret,TreeNode* root){if(!root)return;inorder(ret, root->left);ret.push_back(root->val);inorder(ret, root->right);}vector<int> inorderTraversal(TreeNode* root) {vector<int> ret;inorder(ret,root);return ret;}

三、二叉树后序遍历

二叉树的后序遍历_牛客题霸_牛客网

    void postorder(vector<int>& ret,TreeNode* root){if(!root)return;postorder(ret, root->left);postorder(ret, root->right);ret.push_back(root->val);}vector<int> postorderTraversal(TreeNode* root) {vector<int> ret;postorder(ret,root);return ret;}

四、二叉树层序遍历

求二叉树的层序遍历_牛客题霸_牛客网

队列+BFS

    vector<vector<int> > levelOrder(TreeNode* root) {vector<vector<int>> ret;if(!root)return ret;queue<TreeNode*> q;q.push(root);while(!q.empty()){vector<int> tmp;int sz=q.size();while(sz--){TreeNode* t=q.front();q.pop();tmp.push_back(t->val);if(t->left)q.push(t->left);if(t->right)q.push(t->right);}ret.push_back(tmp);}return ret;}

五、按之字形顺序打印二叉树

按之字形顺序打印二叉树_牛客题霸_牛客网

在前一题的基础上将偶数行数组逆序即可,添加一个标记位就能实现

    vector<vector<int> > Print(TreeNode* pRoot) {vector<vector<int>> ret;if(!pRoot)return ret;queue<TreeNode*> q;q.push(pRoot);//标记位int flag=1;while(!q.empty()){vector<int> tmp;int sz=q.size();while(sz--){TreeNode* t=q.front();q.pop();tmp.push_back(t->val);if(t->left)q.push(t->left);if(t->right)q.push(t->right);}//偶数行逆序即可,别忘了更新flagif(flag%2==0)reverse(tmp.begin(),tmp.end());++flag;ret.push_back(tmp);}return ret;}

六、二叉树最大深度

二叉树的最大深度_牛客题霸_牛客网

请输入文本

    int maxDepth(TreeNode* root) {if(!root)return 0;return 1+max(maxDepth(root->left),maxDepth(root->right));}

七、二叉树中和为某一值的路径(一)

二叉树中和为某一值的路径(一)_牛客题霸_牛客网

当结点为叶子结点的时候才判断,不是在root为空判断,不然比如根结点1,左节点空,右节点2的情况,sum=1,也会输出true,但这不是合法路径

class Solution {int _sum;
public:bool dfs(TreeNode* root, int TmpSum){if(!root)return false;if(!root->left&&!root->right){if(TmpSum+root->val==_sum)return true;return false;}return dfs(root->left,TmpSum+root->val)||dfs(root->right,TmpSum+root->val);}bool hasPathSum(TreeNode* root, int sum) {_sum=sum;return dfs(root,0);}
};

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

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

突然发现题目给的就是二叉搜索树,那中序遍历把结点存起来就行了

#include <vector>
class Solution {vector<TreeNode*> ans;
public://中序遍历将结点存进数组void InOrder(TreeNode*root){if(!root)return;InOrder(root->left);ans.push_back(root);InOrder(root->right);}TreeNode* Convert(TreeNode* pRootOfTree) {if(!pRootOfTree)return nullptr;InOrder(pRootOfTree);for(int i=0;i<ans.size()-1;++i){ans[i]->right=ans[i+1];ans[i+1]->left=ans[i];}return ans[0];}
};

九、对称的二叉树

对称的二叉树_牛客题霸_牛客网

因为我们需要同时访问两颗子树的数据,仅仅使用一个结点是不够的,我们构造另一个函数。

class Solution {
public:bool recursion(TreeNode* root1,TreeNode*root2){if(!root1&&!root2)return true;//注意判断顺序,能运行到判断不等的代码就说明两个结点都存在if(!root1||!root2||root1->val!=root2->val)return false;return recursion(root1->left,root2->right)&&recursion(root1->right, root2->left);}bool isSymmetrical(TreeNode* pRoot) {return recursion(pRoot, pRoot);}
};

十、合并二叉树

合并二叉树_牛客题霸_牛客网

递归做即可

class Solution {
public:TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {if(!t1)return t2;if(!t2)return t1;TreeNode* head=new TreeNode(t1->val+t2->val);head->left=mergeTrees(t1->left,t2->left);head->right=mergeTrees(t1->right, t2->right);return head;}
};

十一、二叉树的镜像

二叉树的镜像_牛客题霸_牛客网

看懂后其实就是每个根节点的左节点变成右节点,右节点变成左节点,左右节点都交换位置,就达成了镜像,做二叉树递归,一定得有从局部到整体的思想。

递归往下,每层递归交换左右子树

class Solution {
public:TreeNode* Mirror(TreeNode* pRoot) {if(pRoot==nullptr)return nullptr;//递归子树TreeNode*left=Mirror(pRoot->left);TreeNode*right=Mirror(pRoot->right);//交换,局部->整体pRoot->left=right;pRoot->right=left;return pRoot;}
};

十二、判断是不是二叉搜索树

判断是不是二叉搜索树_牛客题霸_牛客网

利用二叉搜索树的中序遍历是递增的这一特性判断

#include <climits>
class Solution {
public:int prev=INT_MIN;bool isValidBST(TreeNode* root) {if(!root)return true;if(!isValidBST(root->left))return false;if(root->val<=prev)return false;prev=root->val;if(!isValidBST(root->right))return false;return true;}
};

十三、判断是不是完全二叉树

判断是不是完全二叉树_牛客题霸_牛客网

借助队列实现层序遍历

class Solution {
public:bool isCompleteTree(TreeNode* root) {if(!root)return true;queue<TreeNode*> q;q.push(root);bool flag=false;while(!q.empty()){int sz=q.size();while(sz--){TreeNode* t=q.front();q.pop();//该层遇到空节点if(!t)flag=true;//不是空,把left和right传进来,不过得提前判断该层前面有没有出现空else{   if(flag)return false;q.push(t->left);q.push(t->right);}}}return true;}
};

十四、判断是不是平衡二叉树

判断是不是平衡二叉树_牛客题霸_牛客网

平衡二叉树判断标准:任何左右子树层数相差不超过1

解法一:自顶向下

class Solution {
public://计算树的最大深度int MaxDepth(TreeNode* root){if(!root)return 0;return 1+max(MaxDepth(root->left),MaxDepth(root->right));}bool IsBalanced_Solution(TreeNode* pRoot) {if(!pRoot)return true;//处理该层int LeftDepth=MaxDepth(pRoot->left);int RightDepth=MaxDepth(pRoot->right);if(LeftDepth-RightDepth>1||LeftDepth-RightDepth<-1)return false;//同时左右子树也得平衡return IsBalanced_Solution(pRoot->left)&&IsBalanced_Solution(pRoot->right);}
};

解法二:自底向上

class Solution {
public://计算该子树深度//注意depth是引用传参!!!bool judge(TreeNode* root, int& depth){//空节点深度为0if(root == NULL){ depth = 0;return true;}//递归检查左右子树int left = 0, right = 0;if(judge(root->left, left) == false)  // 检查左子树是否平衡return false;                     // 左子树不平衡,整棵树直接完蛋if(judge(root->right, right) == false) // 同理检查右子树return false;//检查左右子树高度差if(left - right > 1 || left - right < -1)return false;//更新当前节点的深度depth = max(left,right)+1;//运行到这表示平衡return true; }bool IsBalanced_Solution(TreeNode* pRoot) {int depth = 0;return judge(pRoot, depth);}
};

十五、二叉搜索树的最近公共祖先

二叉搜索树的最近公共祖先_牛客题霸_牛客网

class Solution {
public:int lowestCommonAncestor(TreeNode* root, int p, int q) {if(!root)return -1;int MinNum=min(p,q),MaxNum=max(p,q);//=也在要求内if(root->val>=MinNum&&root->val<=MaxNum)return root->val;else if(root->val>=MaxNum)return lowestCommonAncestor(root->left, p, q);else return lowestCommonAncestor(root->right, p, q);}
};

十六、在二叉树中找到两个节点的最近公共祖先

在二叉树中找到两个节点的最近公共祖先_牛客题霸_牛客网

这次不再是二叉搜索树了

既然题目肯定是可以找到公共节点的,所以我们自顶向下遍历即可,遇到相等情况直接返回该局部根,否则就去左右找,左边没有那一定在右边,右边反之。如果左右都有,那么该层root恰好就是我们要的节点。

class Solution {
public:TreeNode*dfs(TreeNode*root,int o1,int o2){if(!root)return nullptr;//此时存在一个节点是局部根的情况//既然我们是自顶向下找的,那么我们是第一次碰到直接返回if(root->val==o1||root->val==o2)return root;//查看左右子树有没有目标节点TreeNode* IfLeftTree=dfs(root->left,o1,o2);TreeNode* IfRightTree=dfs(root->right,o1,o2);//左子树没有,那肯定在右子树if(!IfLeftTree)return IfRightTree;//右子树没有,那一定在左子树if(!IfRightTree)return IfLeftTree;//左右子树都有,那么该root就是目标返回节点return root;}int lowestCommonAncestor(TreeNode* root, int o1, int o2) {return dfs(root,o1,o2)->val;}
};

十七、序列化二叉树

序列化二叉树_牛客题霸_牛客网

直接看官方题解吧,这里我们序列化都采用前序遍历

#include <cstring>
#include <string>
class Solution {
public:void SerializeFunction(TreeNode*root,string &str){if(!root){str+='#';return;}//!当作分割// str+=(root->val+'0')+'!';  +'0'只适用于0~9str+=to_string(root->val)+'!';//前序遍历SerializeFunction(root->left, str);SerializeFunction(root->right, str);}char* Serialize(TreeNode *root) {    if(!root)return "#";string str;SerializeFunction(root, str);//动态开辟成char*类型,不能直接return c_str//因为c_str返回指向常量字符串的指针,存在string缓冲区函数结束会被销毁char* newstr=new char[str.size()+1];strcpy(newstr, str.c_str());newstr[str.size()]='\0';return newstr;}//传地址,整个函数共享一个str位置TreeNode* DeserializeFunction(char**str){if(**str=='#'){(*str)++;return nullptr;}//数字字符串->数字int val=0;while(**str!='!'&&**str!='\0'){val=val*10+**str-'0';//别忘记更新str位置,关于优先级问题能打括号尽量打括号吧(*str)++;}TreeNode*root=new TreeNode(val);//注意判断是否达到末尾,以防越界if(**str=='\0')return root;else (*str)++;//自顶向下构建二叉树root->left=DeserializeFunction(str);root->right=DeserializeFunction(str);return root;}TreeNode* Deserialize(char *str) {if(*str=='#')return nullptr;return DeserializeFunction(&str);}
};

十八、重建二叉树

重建二叉树_牛客题霸_牛客网

找到目标点不断递归细分pre数组和vin数组(构建左右子树前序中序遍历,依据这个顺序构建左右子树->递归)

#include <vector>
class Solution {
public:TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {int n=preOrder.size(),m=vinOrder.size();if(n==0||m==0)return nullptr;TreeNode*root=new TreeNode(preOrder[0]);for(int i=0;i<m;++i){if(preOrder[0]==vinOrder[i]){//构建左子树前序遍历vector<int> LTreePre(preOrder.begin()+1,preOrder.begin()+1+i);//左子树中序遍历vector<int> LTreeVin(vinOrder.begin(),vinOrder.begin()+i);//构建左子树root->left=reConstructBinaryTree(LTreePre,LTreeVin);//右子树也是一样vector<int> RTreePre(preOrder.begin()+i+1,preOrder.end());vector<int> RTreeVin(vinOrder.begin()+i+1,vinOrder.end());root->right=reConstructBinaryTree(RTreePre, RTreeVin);break;}}return root;}
};

十九、输出二叉树的右视图

输出二叉树的右视图_牛客题霸_牛客网

重建二叉树然后输出每层最右边那个

重建二叉树+层序遍历

#include <vector>
class Solution {
public:TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {int n=preOrder.size(),m=vinOrder.size();if(n==0||m==0)return nullptr;TreeNode*root=new TreeNode(preOrder[0]);for(int i=0;i<m;++i){if(preOrder[0]==vinOrder[i]){//构建左子树前序遍历vector<int> LTreePre(preOrder.begin()+1,preOrder.begin()+1+i);//左子树中序遍历vector<int> LTreeVin(vinOrder.begin(),vinOrder.begin()+i);//构建左子树root->left=reConstructBinaryTree(LTreePre,LTreeVin);//右子树也是一样vector<int> RTreePre(preOrder.begin()+i+1,preOrder.end());vector<int> RTreeVin(vinOrder.begin()+i+1,vinOrder.end());root->right=reConstructBinaryTree(RTreePre, RTreeVin);break;}}return root;}vector<int> solve(vector<int>& preOrder, vector<int>& inOrder) {TreeNode* root=reConstructBinaryTree(preOrder,inOrder);vector<int> ret;if(!root)return ret;queue<TreeNode*> q;q.push(root);while(!q.empty()){int sz=q.size();while(sz){TreeNode* t=q.front();q.pop();if(sz==1)ret.push_back(t->val);if(t->left)q.push(t->left);if(t->right)q.push(t->right);--sz;}}return ret;}
};

此篇完。

http://www.dtcms.com/a/537790.html

相关文章:

  • LangChain最详细教程之Chains
  • 声纹识别:声音中的“指纹”重塑无感身份认证
  • RDPWD!ShareClass::UPSendOrders函数中的RDPWD!ShareClass::SC_FlushAndAllocPackage函数分析
  • 怎么建设网站容易被百度抓取app开发公司 无冬
  • 站长字体网页美工培训班
  • 深圳营销型网站dz论坛怎么做视频网站吗
  • 有哪些网站是拐角型wordpress 文章摘要 插件
  • 网站开发项目经验百度移动端网站
  • pc端网站布局中国建设银行网站转账
  • 临沂做外贸网站的公司给一个装修公司怎么做网站
  • Java的异常处理机制
  • 大连三大网络推广网站wordpress百度收录搜索
  • 标准化开放 API 对接工具类 OpenApiHttp 深度解析:高效、安全的接口集成方案
  • 网站空间域名能不能自己续费专注做蔬菜的网站
  • 泰安vx百度关键词如何优化
  • 通感算控一体化-AIBOX提供无人机BVLOS(超视距)飞行的无线通信增强解决方案:5G蜂窝+无线自组网双链路的C2通信方案
  • 东营网站seo顾问一个简单的网站搭建教程
  • 如何检测电脑SSD健康状态?
  • 胶州建设信息网站课件模板下载免费
  • 建立网站顺序网站宽度设计
  • Spring Boot3零基础教程,远程调用 WebClient,笔记74
  • 网上书店电子商务网站建设专业网站开发技术
  • MySQL高可用方案MICmysqlCluster+mysqlRouter
  • 2025-10-25 MXOJ 【CSP-S】-- 模拟四 【郑州一中】record
  • 网络公司发生网站建设费分录响应式自适应织梦网站模板
  • 2025年内蒙古自治区职业院校技能大赛高职组“软件测试”赛项技能操作样题
  • 无锡建设银行网站网战
  • Java(IO流)
  • 管家婆财贸ERP BB118.付款单单据控制
  • 做男性服装的网站网站首页的快照更新慢