【C++】二叉树进阶面试题(上)

目录

[1. 二叉树创建字符串](#1. 二叉树创建字符串)

题目

分析

代码

[2. 二叉树的分层遍历1](#2. 二叉树的分层遍历1)

题目

分析

代码

[3. 二叉树的分层遍历2](#3. 二叉树的分层遍历2)

题目

分析

代码

[4. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先](#4. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先)

题目

分析

代码

[5. 二叉树搜索树转换成排序双向链表](#5. 二叉树搜索树转换成排序双向链表)

题目

分析

代码


1. 二叉树创建字符串

题目

OJ链接

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

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

分析

如下图所示

这道题要求打印出表示二叉树关系的字符串,这样应该很简单,但是又要求省略掉不必要的空括号,这就需要判断什么情况下的括号是不必要的括号,很显然,如果一个结点的左子树为空,但是右子树不为空,这时候代表左子树的那个括号就一定不能省略,在其他情况下则都是可以省略的,根据这些我们可以写出如下代码

代码

cpp 复制代码
class Solution {
public:
    string tree2str(TreeNode* root) {
        string ret;
        if(root==nullptr)
            return "";
        ret+=to_string(root->val);
//当左子树不为空
        if(root->left)
        {
            ret+="(";
            ret+=tree2str(root->left);
            ret+=")";
        }
//当左子树为空,右子树不为空
        if(root->right&&root->left==nullptr)
        {
            ret+="()";
        }
//当右子树不为空
        if(root->right)
        {
            ret+="(";
            ret+=tree2str(root->right);
            ret+=")";
        }
        return ret;
    }
};

2. 二叉树的分层遍历1

题目

OJ链接

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

分析

这道题就是对二叉树进行层序遍历,即根据深度来依次遍历,遍历完上一层的所有结点才能访问下一层的。

这时候我们需要一个变量levelsize来帮助我们记录当前深度下一共有多少个结点,来帮助我们能遍历完当前层的所有结点,并且在遍历上一层结点的同时把下一层结点的个数统计出来,依次循环下去达到我们的目的。

代码

cpp 复制代码
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> vv;
        if (root == nullptr) {
            return vv;
        }
        // 先记录第一层的结点个数(一定为1)
        int levelSize = 1;
        queue<TreeNode*> q;
        // 将第一层的所有结点插入队列(只有一个根节点)
        q.push(root);
        while (!q.empty()) {
            // 记录当前层的所有结点的值
            vector<int> v;
            // 遍历完当前层的所有结点
            while (levelSize--) {
                // 获得当前结点并将该节点弹出
                TreeNode* cur = q.front();
                q.pop();
                v.push_back(cur->val);
                // 将下一层的结点插入到队列
                if (cur->left) {
                    q.push(cur->left);
                }
                if (cur->right) {
                    q.push(cur->right);
                }
            }
            // 刷新levelSize为下一层的结点个数
            levelSize = q.size();
            // 将当前层的所有结点的值填入二维数组
            vv.push_back(v);
        }
        return vv;
    }
};

3. 二叉树的分层遍历2

题目

OJ链接

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

分析

与上一题输出相反,我们可以对上一题得到的二维数组vv进行倒转,即使用reverse函数进行逆置。

在上一题的return vv;前加一个

cpp 复制代码
        reverse(vv.begin(),vv.end());

代码

cpp 复制代码
class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
 vector<vector<int>> vv;
        if (root == nullptr) {
            return vv;
        }
        // 先记录第一层的结点个数(一定为1)
        int levelSize = 1;
        queue<TreeNode*> q;
        // 将第一层的所有结点插入队列(只有一个根节点)
        q.push(root);
        while (!q.empty()) {
            // 记录当前层的所有结点的值
            vector<int> v;
            // 遍历完当前层的所有结点
            while (levelSize--) {
                // 获得当前结点并将该节点弹出
                TreeNode* cur = q.front();
                q.pop();
                v.push_back(cur->val);
                // 将下一层的结点插入到队列
                if (cur->left) {
                    q.push(cur->left);
                }
                if (cur->right) {
                    q.push(cur->right);
                }
            }
            // 刷新levelSize为下一层的结点个数
            levelSize = q.size();
            // 将当前层的所有结点的值填入二维数组
            vv.push_back(v);
        }
        reverse(vv.begin(),vv.end());
        return vv;
    }
};

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

题目

OJ链接

分析

这里我们可以找出p和q路径上的所有祖先结点插入栈中,然后pop出栈对p和q路径上的结点依次比较,从而找到最近的公共祖先结点。

代码

cpp 复制代码
class Solution {
public:
    bool createPath(TreeNode* root, TreeNode* t, stack<TreeNode*>& st)
    {
        if (root == nullptr)
            return false;
        st.push(root);
        if (root == t)
            return true;
        if (createPath(root->left, t, st))
            return true;
        if (createPath(root->right, t, st))
            return true;
        st.pop();
        return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> p_path;
        stack<TreeNode*> q_path;
        //插入p和q路径上的所有结点到栈中
        createPath(root, p, p_path);
        createPath(root, q, q_path);
        //使得两个条路径的结点个数一样
        while (p_path.size() != q_path.size())
        {
            if (p_path.size() > q_path.size())
                p_path.pop();
            else
                q_path.pop();
        }
        //寻找最近的公共结点
        while (p_path.top()!=q_path.top())
        {
            p_path.pop();
            q_path.pop();
        }
        return p_path.top();
    }
};

5. 二叉树搜索树转换成排序双向链表

题目

OJ链接

分析

如果说可以创建新的结点,那这题比较简单,但是题目要求不能创建新节点,只能调整当前结点的指向来完成双向链表的创建。

代码

cpp 复制代码
class Solution {
public:
	void order(TreeNode* root, TreeNode*& preNode)
	{
		if (root == nullptr)
			return;
		if (root->left)
			order(root->left, preNode);
		root->left = preNode;
		if (preNode)
			preNode->right = root;
		preNode = root;
		if (root->right)
			order(root->right, preNode);

	}
	TreeNode* Convert(TreeNode* pRootOfTree) {
		if (pRootOfTree == nullptr)
			return nullptr;
		TreeNode* preNode = nullptr;
		order(pRootOfTree, preNode);
		TreeNode* head = pRootOfTree;
		while (head->left)
		{
			head = head->left;
		}
		return head;
	}
};
相关推荐
云和数据.ChenGuang10 分钟前
运维面试题.云计算面试题集锦
面试·运维面试题·云计算面试题·linux面试题
jokerest12317 分钟前
pwn——test_your_nc1——测试
开发语言·php
碧海蓝天202229 分钟前
接上一主题,C++14中如何设计类似于std::any,使集合在C++中与Python一样支持任意数据?
开发语言·c++·python
醉颜凉33 分钟前
计算(a+b)/c的值
java·c语言·数据结构·c++·算法
周杰伦fans36 分钟前
Java与C#
java·开发语言·c#
zl.rs39 分钟前
对比C++,Rust在内存安全上做的努力
c++·安全·rust
SAP学习成长之路1 小时前
SAP 零售方案 CAR 系统的介绍与研究
大数据·开发语言·sap·abap·零售·car·bapi
机器视觉知识推荐、就业指导1 小时前
Qt/C++基于重力模拟的像素点水平堆叠效果
c++·qt
A_Tai23333331 小时前
MyBatis高级扩展
java·开发语言·mybatis
夏子曦1 小时前
java虚拟机——频繁发生Full GC的原因有哪些?如何避免发生Full GC
java·开发语言