数据结构进阶 二叉树OJ题一

简介: 数据结构进阶 二叉树OJ题一

题目一 根据二叉树创建字符串


给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。


空节点使用一对空括号对 “()” 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。


来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/construct-string-from-binary-tree


b33c3953e71f47009cdc7b9f1deed93c.png


我们先忽略掉题目中要求我们省略括号这个步骤


这个题目其实就是要求我们按照前序遍历的方式遍历整个二叉树 并且将其中的节点变为字符加入到字符串当中去


并且遍历到左右节点之前要加括号 遍历完毕之后要闭合括号


string ans = "";
    string tree2str(TreeNode* root) 
    {
        if (root == nullptr)
        {
            return ans;
        }
        ans += to_string(root->val);
        // 遍历左子树
        ans += '(' ;
        tree2str(root -> left);
        ans += ')' ;
        // 遍历右子树
        ans += '(' ;
        tree2str(root -> right);
        ans += ')' ;
        return ans;
    }


于是我们写出上面的代码 得到的结果如下


510e95de92fe4367a18d775f82458559.png


这里我们可以发现相比于预期的结果 多了很多不必要的括号


首先就是左右子树为空的情况 针对这种情况我们做出这样子的代码优化


if (root -> left)
        {
        ans += '(' ;
        tree2str(root -> left);
        ans += ')' ;
        }
        // 遍历右子树
        if (root -> right)
        {
        ans += '(' ;
        tree2str(root -> right);
        ans += ')' ;
        }


我们可以发现 经过这样子的优化之后就消除了很多空格


a2ffcafa5e9b4fe895ac791190b65904.png

但是还有一种情况没有顾及到

2ad33da4eb8e45e089fa64a0508c9534.png


那就是示例2的情况 此种情况中 左子树为空且右子树不为空 也加上了一个空括号 于是乎我们的条件应该变成这样


root -> left || root -> right


这个条件用的很巧妙


因为当树的左孩子为空的时候才会判断第二个条件 这个时候才能符合左子树为空 并且右子树不为空


完整代码如下


string ans = "";
    string tree2str(TreeNode* root) 
    {
        if (root == nullptr)
        {
            return ans;
        }
        ans += to_string(root->val);
        // 遍历左子树
        if (root -> left || root -> right)
        {
        ans += '(' ;
        tree2str(root -> left);
        ans += ')' ;
        }
        // 遍历右子树
        if (root -> right)
        {
        ans += '(' ;
        tree2str(root -> right);
        ans += ')' ;
        }
        return ans;
    }

运行结果如下


b66ce3186beb47a9a4007dd577a26edc.png


题目二 二叉树的层序遍历


给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。


3d5aae2dea9c47778ca916313f179cca.png


层序遍历的题目我们之前已经做过了 思路也很简单 使用一个队列即可完成


在这道题目还有一个需要我们解决的问题就是如何确定层序遍历的每一层的个数


并且将它们放到vector当中 这里提供一个使用变量levelsize来记录每一层大小的操作

7868056340ef485d9f4e93e54da3755f.png


我们每层遍历完(levelsize为0)的时候确认一次队列的大小


并将其值赋值给levelsize


之后每次出一个数据 levelsizie的大小减一 依此循环


代码表示如下


class Solution {
public:
    vector<vector<int>> vv;
    queue<TreeNode*> q;
    vector<int> v1;
    vector<vector<int>> levelOrder(TreeNode* root) 
    {
        // 如果空树 直接返回一个空的vector
        if (root == nullptr)
        {
            return vv;
        }
        int levelsize = 1;
        q.push(root);
        while (!q.empty())
        {
            if (levelsize != 0)
            {
                TreeNode* front = q.front();
                q.pop();
                v1.push_back(front->val);
                levelsize--;
                if (front->left != nullptr)
                {
                    q.push(front->left);
                }
                if (front->right != nullptr )
                {
                    q.push(front->right);
                }
            }
            else
            {
                vv.push_back(v1);
                v1.clear();
                levelsize = q.size();
            }
        }
        // 为什么这里要再push一次 因为最后一次队列为空的时候没有进循环
        vv.push_back(v1);
        return vv;
    }
};


题目三 二叉树的最近公共祖先


给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。


百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”


来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree


6fb949b84dee4ae18fcae4bdc8758a5d.png

我们首先来分析题目


很明显的可以发现 要满足二叉树的公共祖先则必然满足两个节点分布在根节点的两边


那么知道这个限制条件就简单很多了


首先我们先写出一个搜寻函数


bool find(TreeNode* root , TreeNode* x)
    {
        if (root == NULL)
        {
            return false;
        }
        if (root == x)
        {
            return true;
        }
        return find(root -> left , x) || find(root -> right , x);
    }


在这之后我们设计四个布尔值来确定根节点的位置


bool pleft , pright , qleft , qright;


之后的思路就很简单了


我们只要保证p和q不在同一边


也就是说 pleft与qright相同 或者qleft和pright相同就可以


代码表示如下


class Solution {
public:
    bool find(TreeNode* root , TreeNode* x)
    {
        if (root == NULL)
        {
            return false;
        }
        if (root == x)
        {
            return true;
        }
        return find(root -> left , x) || find(root -> right , x);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if (root == NULL)
        {
            return NULL;
        }
        if (root == p || root == q)
        {
            return root;
        }
        // 再之后我们使用搜寻函数来确定两个节点的左右
        bool pleft , pright , qleft , qright;
        pleft = find(root -> left, p);
        pright = !pleft;
        qleft = find(root -> left , q);
        qright = !qleft;
        if ((pleft && qright) || (pright && qleft))
        {
            return root;
        }
        else if(pleft && qleft)
        {
            return lowestCommonAncestor(root->left ,p,q);
        }
        else if (pright && qright)
        {
            return lowestCommonAncestor(root ->right , p, q);
        }
        else
        {
            return root;
        }
    }
};


运行结果如下


a23c7277124044edb08316bd067bd1a3.png

相关文章
|
10天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
2月前
|
机器学习/深度学习 存储 算法
数据结构实验之二叉树实验基础
本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
98 4
|
2月前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
147 8
|
3月前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
33 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
3月前
|
存储 算法 搜索推荐
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
这篇文章主要介绍了顺序存储二叉树和线索化二叉树的概念、特点、实现方式以及应用场景。
39 0
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
|
3月前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
3月前
|
存储 算法
数据结构与算法学习十六:树的知识、二叉树、二叉树的遍历(前序、中序、后序、层次)、二叉树的查找(前序、中序、后序、层次)、二叉树的删除
这篇文章主要介绍了树和二叉树的基础知识,包括树的存储方式、二叉树的定义、遍历方法(前序、中序、后序、层次遍历),以及二叉树的查找和删除操作。
37 0
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
241 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
40 1
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
71 5