C/C++每日一练(20230427) 二叉树专场(5)

news2024/12/26 9:27:31

目录

1. 从中序与后序遍历序列构造二叉树  🌟🌟

2. 从先序与中序遍历序列构造二叉树  🌟🌟

3. 二叉树展开为链表  🌟🌟

🌟 每日一练刷题专栏 🌟

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏


1. 从中序与后序遍历序列构造二叉树

根据一棵树的中序遍历与后序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

出处:

https://edu.csdn.net/practice/26654112

代码:

#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;

struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution
{
public:
    TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder)
    {
        if (0 == inorder.size() || 0 == postorder.size())
        {
            return NULL;
        }
        return build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
    }
    TreeNode *build(vector<int> &inorder, int i1, int i2, vector<int> &postorder, int p1, int p2)
    {
        TreeNode *root = new TreeNode(postorder[p2]);
        int i = i1;
        while (i <= i2 && postorder[p2] != inorder[i])
        {
            i++;
        }
        int left = i - i1;
        int right = i2 - i;
        if (left > 0)
        {
            root->left = build(inorder, i1, i - 1, postorder, p1, p1 + left - 1);
        }
        if (right > 0)
        {
            root->right = build(inorder, i + 1, i2, postorder, p1 + left, p2 - 1);
        }
        return root;
    }
};

vector<int> preorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> st;
    st.push(root);
    while (!st.empty()) {
        TreeNode* node = st.top();
        st.pop();
        if (node != nullptr) {
            res.push_back(node->val);
            st.push(node->right);
            st.push(node->left);
        }
    }
    return res;
}

string vectorToString(vector<int> vect) {
    stringstream ss;
	ss << "[";
    for (size_t i = 0; i < vect.size(); i++) {
    	ss << vect[i] << (i < vect.size() - 1 ? "," : "");
    }
    ss << "]";
    return ss.str();
}

int main()
{
    Solution s;
    vector<int> inorder = {9,3,15,20,7};
    vector<int> postorder = {9,15,7,20,3};
    TreeNode* root = s.buildTree(inorder, postorder);
    vector<int> preorder = preorderTraversal(root);
    cout << vectorToString(preorder) << endl;
    return 0;
}

输出:

[3,9,20,15,7]


2. 从先序与中序遍历序列构造二叉树

根据一棵树的先序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

先序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

出处:

与上题类似,已知三种遍历中的两个且有中序,就能确定一棵二叉树。如果只有先序、后序,因为不能确定根的位置,所以无法确定。

代码:

#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;

struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.empty() || inorder.empty()) {
            return nullptr;
        }
        unordered_map<int, int> pos;
        for (int i = 0; i < (int)inorder.size(); ++i) {
            pos[inorder[i]] = i;
        }
        return build(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1, pos);
    }
    TreeNode* build(vector<int>& preorder, int p1, int p2, vector<int>& inorder, int i1, int i2, unordered_map<int, int>& pos) {
        if (p1 > p2 || i1 > i2) {
            return nullptr;
        }
        int rootVal = preorder[p1];
        int i = pos[rootVal];
        TreeNode* root = new TreeNode(rootVal);
        root->left = build(preorder, p1 + 1, p1 + i - i1, inorder, i1, i - 1, pos);
        root->right = build(preorder, p1 + i - i1 + 1, p2, inorder, i + 1, i2, pos);
        return root;
    }
};

vector<int> postorderTraversal(TreeNode* root) {
    vector<int> res;
    if (root == nullptr) {
        return res;
    }
    stack<TreeNode*> st1, st2;
    st1.push(root);
    while (!st1.empty()) {
        TreeNode* node = st1.top();
        st1.pop();
        st2.push(node);
        if (node->left != nullptr) {
            st1.push(node->left);
        }
        if (node->right != nullptr) {
            st1.push(node->right);
        }
    }
    while (!st2.empty()) {
        res.push_back(st2.top()->val);
        st2.pop();
    }
    return res;
}

string vectorToString(vector<int> vect) {
    stringstream ss;
	ss << "[";
    for (size_t i = 0; i < vect.size(); i++) {
    	ss << vect[i] << (i < vect.size() - 1 ? "," : "");
    }
    ss << "]";
    return ss.str();
}

int main()
{
    Solution s;
    vector<int> preorder = {3,9,20,15,7};
    vector<int> inorder = {9,3,15,20,7};
    TreeNode* root = s.buildTree(preorder, inorder);
    vector<int> postorder = postorderTraversal(root);
    cout << vectorToString(postorder) << endl;
    return 0;
}

输出:

[9,15,7,20,3]


3. 二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。

示例 1:

输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [0]
输出:[0]

提示:

  • 树中结点数在范围 [0, 2000] 内
  • -100 <= Node.val <= 100

进阶:你可以使用原地算法(O(1) 额外空间)展开这棵树吗?

出处:

https://edu.csdn.net/practice/25405424

代码:

#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;

struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution
{
public:
    void rconnect(TreeNode *&node, TreeNode *pmove)
    {
        if (pmove == nullptr)
            return;
        node->right = new TreeNode(pmove->val);
        node->left = nullptr;
        node = node->right;
        rconnect(node, pmove->left);
        rconnect(node, pmove->right);
    }
    void flatten(TreeNode *root)
    {
        if (root == nullptr)
            return;
        TreeNode *head = new TreeNode(null);
        TreeNode *newroot = head;
        rconnect(head, root);
        newroot = newroot->right->right;
        root->right = newroot;
        root->left = nullptr;
    }
};

TreeNode* buildTree(vector<int>& nums)
{
    if (nums.empty()) return nullptr;
	TreeNode *root = new TreeNode(nums.front());
    queue<TreeNode*> q;
    q.push(root);
    int i = 1;
    while(!q.empty() && i < nums.size())
    {
        TreeNode *cur = q.front();
        q.pop();
        if(i < nums.size() && nums[i] != null)
        {
            cur->left = new TreeNode(nums[i]);
            q.push(cur->left);
        }
        i++;
        if(i < nums.size() && nums[i] != null)
        {
            cur->right = new TreeNode(nums[i]);
            q.push(cur->right);
        }
        i++;
    }
    return root;
}

vector<int> preorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> st;
    st.push(root);
    while (!st.empty()) {
        TreeNode* node = st.top();
        st.pop();
        if (node != nullptr) {
            res.push_back(node->val);
            st.push(node->right);
            st.push(node->left);
        }
        else
        	res.push_back(null);
    }
    while (res.back()==null)
    	res.pop_back();
    return res;
}
 
string vectorToString(vector<int> vect) {
    stringstream ss;
	ss << "[";
    for (size_t i = 0; i < vect.size(); i++)
	{
        ss << (vect[i] == null ? "null" : to_string(vect[i]));
        ss << (i < vect.size() - 1 ? "," : "]");
    }
    return ss.str();
}
  
int main() {
	Solution s;
    vector<int> nums = {1,2,5,3,4,null,6};  
    TreeNode* root = buildTree(nums);  
    s.flatten(root); 
    cout << vectorToString(preorderTraversal(root)) << endl;
    return 0;  
}

输出:

[1,null,2,null,3,null,4,null,5,null,6]


🌟 每日一练刷题专栏 🌟

持续,努力奋斗做强刷题搬运工!

👍 点赞,你的认可是我坚持的动力! 

🌟 收藏,你的青睐是我努力的方向! 

评论,你的意见是我进步的财富!  

 主页:https://hannyang.blog.csdn.net/

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏

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

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

相关文章

微信小程序php+python+nodejs+vue 高校工资管理系统

在线公益知识练习及测试系统是随着计算机技术和互联网技术的发展而产生的一种的新的练习及测试模式&#xff0c;与传统的纸质化练习及测试不同&#xff0c;在线系统提高了练习或测试的效率&#xff0c;减少了纸张的浪费&#xff0c;减轻了教师的评卷压力&#xff0c;同时也为参…

易观千帆 | 金融机构如何保证用户体验长期可持续?

易观&#xff1a;用户体验正逐渐成为金融机构的命脉。 数字经济时代的到来&#xff0c;金融机构面临着来自内部和外部的双重压力。一方面&#xff0c;互联网金融企业凭借强大的技术能力以及人才优势&#xff0c;通过互联网运营的模式迅速响应客户需求&#xff0c;吸引了大量用户…

自定义Feign日志

文章目录 开篇定位Feign是怎么打印日志的&#xff1f;自定义FeignLogger实现 开篇 在上一篇Feign打印日志文章中&#xff0c;已经成功打印了FeignClient请求服务的日志信息&#xff0c;但是默认打印的日志太过零散&#xff0c;不是我们想要的。怎么能自定义日志打印的格式和内…

系统分析师《企业信息化战略与实施》高频知识点二

企业信息化战略与实施---系统建模 组织结构是一个企业内部部门的划分以及相互之间的关系&#xff0c;每个企业都有自己的组织结构图&#xff0c;它将企业分成若干部分&#xff0c;标明行政隶属关系。组织结构图是一种树结构&#xff0c;树的分支是根据上下级和行政隶属关系绘制…

二叉树 + 技巧

题目难度备注2471. 逐层排序二叉树所需的最少操作数目1635BFS 置换环 离散化2641. 二叉树的堂兄弟节点 II1677BFS 文章目录 周赛二叉树问题[2471. 逐层排序二叉树所需的最少操作数目](https://leetcode.cn/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-l…

【AI绘画】云服务器部署stable-diffusion-webui保姆级教程

1.背景 之前给大家写过Mac苹果笔记本上部署stable-diffusion-webui的教程&#xff0c;知乎链接&#xff1a; 【奶奶看了也不会】AI绘画 Mac安装stable-diffusion-webui绘制AI妹子保姆级教程 但是安装过程就花了一天的时间&#xff0c;各种问题处理起来真是苦不堪言。。。而且…

如何解决生产缺料问题?

对于一个生产型企业来说&#xff0c;生产缺料是管理中的疑难问题之一。 生产缺料导致的最直接的危害就有两个&#xff1a; 第一就是不能准时交货&#xff0c;降低企业信用&#xff0c;情况严重可能导致根据合同赔款&#xff0c;甚至丢失客户。 第二个危害就是增加了生产成本…

部署LVS-DR 集群及实验

一、LVS-DR工作原理 LVS-DR&#xff08;Linux Virtual Server Director Server&#xff09;工作模式&#xff0c;是生产环境中最常用的一种工作模式。 #①LVS-DR 模式&#xff0c;Director Server 作为群集的访问入口&#xff0c;不作为网关使用&#xff1b; #②节点 Directo…

ueditor富文本编辑器上传木马图片或木马文件漏洞

漏洞分析&#xff1a; ueditor插件目录一般都自带index.html文件&#xff08;完整demo文件&#xff09;&#xff0c;这个文件原来是用来测试插件功能的&#xff0c;但粗心的程序员们&#xff0c;开发好项目后&#xff0c;都忘记删除这个demo文件了&#xff0c;导致黑客可以很轻…

微服务不是本地部署的最佳选择,不妨试试模块化单体

微服务仅适用于成熟产品 关于从头开始使用微服务&#xff0c;马丁・福勒&#xff08;Martin Fowler&#xff09;总结道&#xff1a; 1. 几乎所有成功的微服务都是从一个过于庞大而不得不拆分的单体应用开始的。 2. 几乎所有从头开始以微服务构建的系统&#xff0c;最后都会因…

win11安装双系统ubuntu20.04指导

目录 一、制作U盘启动盘二、硬盘分区2.1方法2.2分区过程 三、安装系统3.1进入U盘启动3.2安装ubuntu3.3设置启动项 四、更新软件五、遇到的问题5.1不能连接WIFI 电脑型号&#xff1a;联想拯救者Y7000P 2023 无线网卡型号&#xff1a;WIFI 6E AX211 160MHz 系统版本&#xff1a;w…

借助尾号限行 API 实现限行规则应用的设计思路分析

引言 尾号限行是指根据车牌号的末尾数字&#xff0c;规定某些时段内不能在特定区域行驶&#xff0c;这是城市交通管理的一种措施。尾号限行政策的实施可以缓解城市交通拥堵问题&#xff0c;减少环境污染和交通事故等问题。 尾号限行 API 是一种提供已知所有执行限行政策的城市…

iSulad+Kuasar:管理面资源消耗锐减 99%的新一代统一容器运行时解决方案

随着云计算和容器技术的不断发展&#xff0c;容器引擎和容器运行时已经成为了云原生时代的基石&#xff0c;它们负责了容器生命周期的管理以及容器运行过程中环境的创建和资源的配置。openEuler 社区基于容器引擎项目 iSulad[1]在解决容器运行效率、安全性以及隔离性等问题上进…

DVWD-Command Injection Low/Medium/High低中高级别

「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 Command Injection 一、Low级别二、Medium级别三、High级别 命令注入这关是一个Ping测试功…

《港联证券》半导体复苏预期“抢跑”产业现实 细分市场缓慢回温

虽然说没有一个冬季不可逾越&#xff0c;但本轮“抢跑”的半导体复苏预期&#xff0c;不得不继续面对工业缓慢复苏的实际。 自2022年下半年以来&#xff0c;资本商场上半导体复苏接棒“缺芯”成为关注焦点&#xff0c;部分半导体职业个股迅速收复跌幅&#xff0c;刷新阶段高点&…

Apache ActiveMQ 远程代码执行漏洞 (CVE-2016-3088)复现

当前漏洞环境部署在vulhub,当前验证环境为vulhub靶场&#xff08;所有实验均为虚拟环境&#xff09; 实验环境&#xff1a;攻击机----kali 靶机&#xff1a;centos7 1、进入环境cd activemq/CVE-2016-3088/&#xff08;靶机&#xff09; 2、启动环境&#xff1a;docker-compos…

设备健康管理软件如何帮助企业优化设备维保计划?

基于AI和工业互联网技术的新型设备管理系统&#xff0c;可以通过实时监测设备运行状态、预测潜在故障、提供预防性维护建议等方式&#xff0c;实现设备管理的数字化和智能化。该类设备管理系统的核心功能一般包括设备状态监测、故障预测、预防性维护、故障知识库管理等&#xf…

Java字节码指令

Java代码运行的过程是Java源码->字节码文件(.class)->运行结果。 Java编译器将Java源文件&#xff08;.java&#xff09;转换成字节码文件(.class)&#xff0c;类加载器将字节码文件加载进内存&#xff0c;然后进行字节码校验&#xff0c;最后Java解释器翻译成机器码。 …

第六届中国软件开源创新大赛——飞桨赛题新鲜出炉,速来pick!

最近想要充个电&#x1f50b; 飞桨邀你开启开源贡献之旅 寻找那个最“会”的你 顶级开源项目、资深研发指导、高阶开发者合作交流&#xff0c;‍‍ Buff 叠满&#xff01; 技能提升、丰富简历、高额奖金&#xff0c; 你还不心动&#xff1f; 赛事简介 中国软件开源创新大赛已成…

聊聊StarRocks向量化执行引擎-过滤操作

聊聊StarRocks向量化执行引擎-过滤操作 StarRocks是开源的新一代极速MPP数据库&#xff0c;采用全面向量化技术&#xff0c;充分利用CPU单核资源&#xff0c;将单核执行性能做到极致。本文&#xff0c;我们聊聊过滤操作是如何利用SIMD指令进行向量化操作。 过滤操作的SIMD向量化…