二叉树超级经典OJ题

news2025/1/12 6:55:53

目录

  • 1.根据二叉树创建字符串
  • 2.二叉树的层序遍历
  • 3.二叉树的层序遍历II
  • 4.二叉树的最近公共祖先
  • 5.二叉搜索树与双向链表
  • 6.从前序与中序遍历序列构造二叉树

1.根据二叉树创建字符串

根据二叉树创建字符串
给你二叉树的根节点root,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。空节点使用一对"()"表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

解析:
通过题目大家第一反应应该是用递归来处理,是的,通过阅读题目,我们知道有些空串是可以省略的。那省略的规则是什么呢?

1.左右都为空,省略掉
2.左子树不为空,右子树为空,省略掉
3.左子树为空,右子树不为空,不能省略

通过这思路我们可以使用递归去写了,代码如下:

class Solution {
public:
    string tree2str(TreeNode* root) {
        if(root == nullptr)
        {
            return string();
        }

        string str;
        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;
    }
};

2.二叉树的层序遍历

二叉树的层序遍历
给你二叉树的根节点root,返回其节点值的层序遍历,即逐层的从左到右访问所有节点。
在这里插入图片描述
解析:
通过题目意思和输入输出的方式,我们可以使用队列,先入队列的先出队列,当前一层的节点都出队列时,下一层的的节点都进队列,此时下一层的节点个数即是levelSzie = q.size(),通过levelSize控制一层一层出,使用vector对出队列的节点进行保存即可。

代码如下:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> q;
        size_t levelSize = 0;
        if(root)
        {
            q.push(root);
            levelSize = 1;
        }

        vector<vector<int>> vv;
        while(!q.empty())
        {
            //控制一层一层出
            vector<int> v;
            for(size_t i=0;i<levelSize;i++)
            {
                TreeNode* front = q.front();
                q.pop();
                v.push_back(front->val);

                if(front->left)
                {
                    q.push(front->left);
                }

                if(front->right)
                {
                    q.push(front->right);
                }
            }
            vv.push_back(v);
            //当前层出完了,下一层都进队列,队列的size就是下一层的数据个数
            levelSize = q.size();
        }
        return vv;
    }
};

3.二叉树的层序遍历II

二叉树的层序遍历II
在这里插入图片描述
解析:
大家发现这题的结果与上一题有什么区别吗?是不是把上一题的结果逆置一下就行了,没错,还有其他思路,但这个较为简单。

代码如下:

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> q;
        size_t levelSize = 0;
        if(root)
        {
            q.push(root);
            levelSize = 1;
        }

        vector<vector<int>> vv;
        while(!q.empty())
        {
            //控制一层一层出
            vector<int> v;
            for(size_t i=0;i<levelSize;i++)
            {
                TreeNode* front = q.front();
                q.pop();
                v.push_back(front->val);

                if(front->left)
                {
                    q.push(front->left);
                }

                if(front->right)
                {
                    q.push(front->right);
                }
            }
            vv.push_back(v);
            //当前层出完了,下一层都进队列,队列的size就是下一层的数据个数
            levelSize = q.size();
        }
        reverse(vv.begin(),vv.end());//逆置

        return vv;
    }
};

4.二叉树的最近公共祖先

二叉树的最近公共祖先
在这里插入图片描述
解析:
思路一:时间复杂度:O(H*N),H是树的高度
这个找公共祖先有什么规则吗?观察下面的图:
在这里插入图片描述
可以知道:一个是它左子树的节点,一个是它右子树的节点,那么它就是最近公共祖先。
代码如下:

class Solution {
public:
    bool Find(TreeNode* sub,TreeNode* x)
    {
        if(sub == nullptr)
        {
            return false;
        }
        if(sub == x)
        {
            return true;
        }

        return Find(sub->left,x) || Find(sub->right,x);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == nullptr)
        {
            return nullptr;
        }

        if(p == root || q == root)
        {
            return root;
        }
        //题目给出p、q一定在二叉树中,所以可以这样写
        bool pInleft,pInright,qInleft,qInright;
        pInleft = Find(root->left,p);
        pInright = !pInleft;
        qInleft = Find(root->left,q);
        qInright = !qInleft;

        //如果一个在左子树,一个在右子树,则根节点为结果
        //如果都在左,递归到左子树去找
        //如果都在右,递归到右子树去找
        if((pInleft&&qInright)||(pInright&&qInleft))
        {
            return root;
        }
        else if(pInleft&&qInleft)
        {
           return lowestCommonAncestor(root->left, p,q);
        }
        else if(pInright&&pInright)
        {
            return lowestCommonAncestor(root->right, p,q);
        }
        else
        {
            //理论上不会走到这
            return nullptr;
        }
    }
};

思路二:上面的时间复杂度为O(H*N),可不可以优化成 O(N)呢?怎么做?
可以使用一个栈,将p,q的路径进行保存,进而转化为链表相交,求交点即可。
代码如下:

class Solution {
public:
    bool FindPath(TreeNode* root,TreeNode* x,stack<TreeNode*>& path)
    {
        if(root == nullptr)
        {
            return false;
        }
        path.push(root);
        if(root == x)
        {
            return true;
        }
        if(FindPath(root->left,x,path))
        {
            return true;
        }

        if(FindPath(root->right,x,path))
        {
            return true;            
        }

        path.pop();
        return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> pPath,qPath;
        FindPath(root,p,pPath);
        FindPath(root,q,qPath);

        //类似链表相交
        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();
    }
};

5.二叉搜索树与双向链表

二叉搜索树与双向链表
在这里插入图片描述
代码如下:

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) {
		if(pRootOfTree == nullptr)
		{
			return nullptr;
		}
        TreeNode* prev = nullptr;
		InOrderConvert(pRootOfTree,prev);

		TreeNode* head = pRootOfTree;
		while(head->left)
		{
			head = head->left;
		}

		return head;
    }
};

6.从前序与中序遍历序列构造二叉树

从前序与中序遍历序列构造二叉树
在这里插入图片描述
思路:前序可以确定根节点,中序分割左右子树。
代码如下:

class Solution {
public:
    TreeNode* _buildTree(vector<int>& preorder,vector<int>& inorder,int& previ,int inbegin,int inend)
    {
        if(inbegin>inend)
        {
            return nullptr;
        }
        TreeNode* root = new TreeNode(preorder[previ++]);
        //分割中序
        int ini = inbegin;
        while(ini<=inend)
        {
            if(inorder[ini] == root->val)
            {
                break;
            }
            else
            {
                ++ini;
            }
        }
        //[inbegin,ini-1] ini [ini+1,inend]
        root->left = _buildTree(preorder,inorder,previ,inbegin,ini-1);
        root->right = _buildTree(preorder,inorder,previ,ini+1,inend);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int i=0;
        return _buildTree(preorder,inorder,i,0,inorder.size()-1);
    }
};

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

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

相关文章

编码器M法测速仿真(Simulink)

编码器M法和T法测速的详细讲解可以参看下面的文章链接,这里不再赘述,这里主要介绍Simulink里建模仿真,带大家从另一个角度理解编码器测速原理。 PLC通过编码器反馈值计算速度的推荐做法(算法解析+ST代码)_RXXW_Dor的博客-CSDN博客_编码器计算速度程序实例PLC如何测量采集编…

Power BI中类似Vlookup的查询筛选功能如何实现

一、问题描述 在Excel中有一个非常经典的函数Vlookup&#xff0c;可以通过首列查找&#xff0c;返回相对应的其他列的值。这种功能&#xff0c;在Power BI中没有Vlookup函数&#xff0c;那么该如何实现这一功能呢&#xff1f;下面通过一个实例做分析演示。 二、数据源 已知某…

厚积薄发打卡Day114:Debug设计模式:设计原则(二)<接口隔离原则、迪米特法则>

厚积薄发打卡Day114&#xff1a;Debug设计模式&#xff1a;设计原则&#xff08;二&#xff09;<接口隔离原则、迪米特法则> 接口隔离原则 定义 用多个专门的接口&#xff0c;而不使用单一的总接口&#xff0c;客户端不应该依赖它不需要的接口 一个类对一个类的依赖应…

如何将 Spring Boot 项目提交到 Gitee 进行远程管理?

如何将初始化完成的 Spring Boot 项目&#xff0c;提交的 Gitee 仓库&#xff0c;进行远程管理&#xff1f; 目录 如何将初始化完成的Spring Boot项目&#xff0c;提交的Gitee仓库&#xff0c;进行远程管理&#xff1f; 0. 环境说明 1.创建并初始化Spring Boot项目 2.创建…

如何设计一个 70w 在线人数的弹幕系统 ?

背景 现在的抖音、快手等一系列能支持直播的软件如何做到的同一时间万人发弹幕的功能的&#xff1f; 问题分析 带宽压力&#xff1b; 弱网导致的弹幕卡顿、丢失&#xff1b; 性能与可靠性。 带宽优化 启用Http压缩 HTTP压缩是指在Web服务器和浏览器间传输压缩文本内容的方…

网络— — 二层交换机

网络— — 二层交换机 1 交换机端口 g0/3 g&#xff1a;1000M/s0&#xff1a;模块号3&#xff1a;接口号 每个端口网速&#xff1a; Ethernet 10M/s FastEthernet 100M/s GigabitEthernet 1000M/s TenGigabitEthernet 10000Mb/s 2 数据链路层&#xff08;2层&#xff09; Data…

python图像处理(opencv入门)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面我们讨论了fpga的基本操作,这些都是作为整个图像处理的基础部分进行学习的,本质上还是希望用fpga来对部分算法进行加速处理。当然,fpga实现的只是一部分算法,并不是所有的算…

【手写 Promise 源码】第二篇 - Promise 功能介绍与特性分析

一&#xff0c;前言 上一篇&#xff0c;对 Promise 进行了简单介绍&#xff0c;主要涉及以下几个点&#xff1a; Promise 简介和基本使用&#xff1b;Promise 和 callback 对比&#xff1b;Promise 的重要性和作用&#xff1b;Promise 使用场景&#xff1a;Promisify 封装&am…

Python Flask 框架设置响应头,一篇文章学明白

flask 响应头设置&#x1f4d6; 导读&#x1f4d6; Python Flask 设置响应头&#x1f389; response.headers 属性&#x1f389; flask.abort() 函数返回特定状态码&#x1f4d6; Flask 中可设置的响应头参数&#x1f4d6; 其他关于响应头的配置&#x1f381; 使用中间件&#…

[Python]调用pytdx的代码示例

安装pytdxpip install pytdx简单示范from pytdx.hq import TdxHq_API api TdxHq_API() # 数据获取接口一般返回list结构&#xff0c; with api.connect(119.147.212.81, 7709): # 返回普通listdata api.get_security_bars(9, 0, 000001, 0, 10) print(data)输出结果[Ordered…

康巴丝(compas)某Wi-Fi万年历无法自动校时的问题

笔者前两年购买过一块康巴丝牌的电子万年历&#xff0c;该万年历的最大特点可以通过Wi-Fi联网自动校时。 后来的某一天&#xff0c;笔者将原来的H3C AP&#xff08;11AC&#xff09;升级为锐捷AP&#xff08;11AX&#xff09;。 在之后的几个月中&#xff0c;发现这块电子万年…

Linux常用命令——setsebool命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) setsebool 修改SElinux策略内各项规则的布尔值 补充说明 setsebool命令是用来修改SElinux策略内各项规则的布尔值。setsebool命令和getsebool命令是SELinux修改和查询布尔值的一套工具组。SELinux的策略与规则…

【云原生】Prometheus 监控系统的初步了解与系统搭建

内容预知 前言 1. Prometheus的相关知识 1.1 Prometheus的认识与了解 1.2 Prometheus的特点 1.3 Prometheus存储引擎TSDB 的特点优势 1.4 Prometheus 的生态组件 &#xff08;1&#xff09;Prometheus server &#xff08;2&#xff09;Client Library &#xff08;3&a…

主流的操作系统(带你快速了解)

&#x1f4dc; “作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴。 &#x1f341; 操作系统【带你快速了解】对于电脑来说&#xff0c;如果说…

如何安装双系统与多系统(带你快速了解)

&#x1f4dc; “作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴。 &#x1f341; 操作系统【带你快速了解】对于电脑来说&#xff0c;如果说…

开放式基金净值历史数据 API 数据接口

开放式基金净值历史数据 API 数据接口 实时净值&#xff0c;历史数据&#xff0c;多维度指数参数。 1. 产品功能 支持所有开放式基金净值历史数据查询&#xff1b;可定义查询指标与时间范围&#xff1b;支持所有开放式基金净值历史数据查询&#xff1b;不同的输入指标返回不同…

java-List

java-List1. 预备知识-泛型(Generic)1.1 泛型的引入1.2 泛型的分类1.3 泛型类的定义的简单演示1.4 泛型背后作用时期和背后的简单原理1.5 泛型类的使用1.6 泛型总结2. 预备知识-包装类(Wrapper Class)2.1 基本数据类型和包装类直接的对应关系2.2 包装类的使用&#xff0c;装箱(…

Windows压缩工具 “ Bandizip与7-zip ”(带你快速了解)

&#x1f4dc; “作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴。 &#x1f341; 操作系统【带你快速了解】对于电脑来说&#xff0c;如果说…

机器视觉在烟草领域中的应用

一个不知名大学生&#xff0c;江湖人称菜狗 original author: jacky Li Email : 3435673055qq.com Time of completion&#xff1a;2023.1.26 Last edited: 2023.1.26 目录 机器视觉在烟草领域中的应用 烟叶外观检测 烟末原料异物检测 叶梗烟丝缺陷检测 香烟过滤嘴外型检测…

(21)go-micro微服务logstash使用

文章目录一 Logstash介绍二 Logstash作用三 Logstash工作原理四 Logstash安装1.拉取镜像2.运行命令3.查看是否运行五 Logstash使用六 最后一 Logstash介绍 Logstash是具有实时流水线能力的开源的数据收集引擎。Logstash可以动态统一不同来源的数据&#xff0c;并将数据标准化到…