数据结构进阶 二叉树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

相关文章
|
5天前
|
算法 编译器 C语言
数据结构——二叉树四种遍历的实现-3
数据结构——二叉树四种遍历的实现
数据结构——二叉树四种遍历的实现-3
|
5天前
|
存储
数据结构——二叉树四种遍历的实现-2
数据结构——二叉树四种遍历的实现
数据结构——二叉树四种遍历的实现-2
|
5天前
|
机器学习/深度学习
数据结构——二叉树四种遍历的实现-1
数据结构——二叉树四种遍历的实现
数据结构——二叉树四种遍历的实现-1
|
5天前
|
数据可视化 数据挖掘 数据处理
【Python进阶(七)】——Series数据结构
【Python进阶(七)】——Series数据结构
|
5天前
【数据结构】二叉树的三种遍历(非递归讲解)
【数据结构】二叉树的三种遍历(非递归讲解)
11 1
|
5天前
|
存储
【数据结构】二叉树相关oj题(一)
【数据结构】二叉树相关oj题(一)
11 1
|
5天前
|
容器
【栈与队列】栈与队列的相互转换OJ题
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
11 0
|
5天前
|
存储 分布式数据库
[数据结构]~二叉树
[数据结构]~二叉树
|
5天前
|
机器学习/深度学习 算法 测试技术
【单调栈】3113. 边界元素是最大值的子数组数目
【单调栈】3113. 边界元素是最大值的子数组数目
|
4天前
|
前端开发 JavaScript 算法
JavaScript 中实现常见数据结构:栈、队列与树
JavaScript 中实现常见数据结构:栈、队列与树