数据结构:二叉树OJ题(基础版)

前言

更完两期二叉树的知识之后,来做几道oj题巩固一下基础


一、翻转二叉树

链接:leetcode链接

还是分治思想,将问题分解成左子树和右子树交换,遇到空树停止

采用递归算法做题

C++ 复制代码
 TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr)
        return nullptr;

        swap(root->left,root->right);

        invertTree(root->left);
        invertTree(root->right);

        return root;
    }

二、另一棵树的子树

链接:leetcode链接

我们可以分解子问题,是不是当前树的子树,是不是左子树的子树,是不是右子树的子树。

细节:如果不是当前树的子树,不应该返回false,而应该继续在左右子树寻找

C++ 复制代码
bool isSame(TreeNode* a,TreeNode* b)
    {
        if(a == nullptr && b == nullptr)
        return true;

        if(a == nullptr || b == nullptr)
        return false;

        if(a->val != b->val)
        return false;

        return isSame(a->left,b->left)
            && isSame(a->right,b->right);
    }

    bool isSubtree(TreeNode* root, TreeNode* subRoot) {
        if(root == nullptr)
        return false;

        if(root->val == subRoot->val)
        {
            bool ret = isSame(root,subRoot);
            if(ret) return true;
        }

        return isSubtree(root->left,subRoot)
            || isSubtree(root->right,subRoot);
    }

三、二叉树的构建及遍历

链接:牛客链接

思路:

中序遍历很简单,很容易实现

这里,比较难的地方是,如何从先序遍历的序列中构建出二叉树

ok,我的思路是这样的:

先去构建当前树,再去构建左子树,再去构建右子树,符合先序遍历的顺序

很明显,这又是一个递归算法。

那么核心就是如何构建好当前树

遇到'#',就代表遇到空节点,遇到其他字符,就正常构建

注意:要传参控制string的下标,不然,没办法结束。

C++ 复制代码
#include <iostream>
using namespace std;


struct TreeNode
{
    TreeNode* left = nullptr;
    TreeNode* right = nullptr;
    char val;
};


TreeNode* Creater(string& s,int& i)
{
    TreeNode* root = new TreeNode;
    if(s[i] == '#')
    {
    i++;
    return nullptr;
    }

    root->val = s[i++];

    root->left = Creater(s, i);
    root->right = Creater(s, i);

    return root;
}

void InOrder(TreeNode* root)
{
    if(root == nullptr)
    return ;

    InOrder(root->left);
    cout << root->val << " ";
    InOrder(root->right);
}

int main() {
   string s;
   cin >> s;
   int i = 0;
   TreeNode* root = Creater(s,i);
   InOrder(root);
   cout << endl;
   return 0;
}

四、对称二叉树链接:

链接:leetcode链接

思路:我们这样想,如何比较两棵树是否对称呢?

记为root_a树和root_b树

显然,需要

(1) root_a树的根节点与root_b树的根节点值相等

(2) 需要root_a树的左子树和root_b树的右子树相等

(3) 需要root_a树的右子树和root_b树的左子树相等

空树为最小子问题

C++ 复制代码
 bool isMirror(TreeNode* left, TreeNode* right) {
       if(left == nullptr && right == nullptr)
       return true;

       if(left == nullptr || right == nullptr)
       return false;

       if(left->val != right->val)
       return false;

       return isMirror(left->left,right->right)
           && isMirror(left->right,right->left);
    }

    bool isSymmetric(TreeNode* root) {
        if (root == nullptr)
            return true;

        return isMirror(root->left,root->right);
    }

五、层序遍历

链接:leetcode链接

注意:该题目不仅仅是层序遍历,另外要求将每一层分开输出。
核心点在于,如何在层序遍历时区分二叉树每一层

层序遍历时的规律:

用队列存储节点,

可以发现,每次出完一层之后,

恰好下一层的所有节点正好进入队列

也就是队列中剩余元素的个数就是下一层的节点的个数

(读者可尝试自己画图分析)

依照次规律,我们可以另外设置一个变量,来记录每一层需要输出的个数。

C++ 复制代码
vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> q;
        if(root == nullptr)
        return {};
        vector<vector<int>> vv;
        q.push(root);
        
        int levelSize = 1;

        while(!q.empty())
        {
            vector<int> v;
            while(levelSize--)
            {
            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);
            }

            levelSize = q.size();
            vv.push_back(v);
        }

        return vv;
    }

六、判断是不是完全二叉树

链接:牛客链接

思路:

根据完全二叉树层序遍历的规律

出完上一层的同时,下一层全部进入队列

所以,我们可以这么操作

我们不管出队列的节点的左节点和右节点是否为nullptr,都进入队列。

当我们出到nullptr的时候,我们就跳出循环

去检查队列中剩余的元素

如果有非空元素,则并不是完全二叉树,如果全部都是空,则是完全二叉树。

为什么可以这么操作呢?

当我们出到nullptr的时候,如果后面有非空节点,那么他一定是nullptr节点前面节点的子节点,他一定进入了队列。

(这点理解清楚,这道题目就没问题了,读者可以画图尝试理解)

C++ 复制代码
bool isCompleteTree(TreeNode* root) {
        queue<TreeNode*> q;
        q.push(root);

        while(!q.empty())
        {
            TreeNode* front = q.front();
            q.pop();

            if(front != nullptr)
            {
                q.push(front->left);
                q.push(front->right);
            }
            else break;
        }

        while(!q.empty())
        {
            TreeNode* front = q.front();
            if(front != nullptr)
            return false;
            q.pop();
        }

        return true;
    }

ok,先讲着6个题目吧,后面更复杂的题目,会在后续博客中进行更新

相关推荐
勇敢滴勇1 小时前
【排序算法】插入排序_直接插入排序、希尔排序
c语言·数据结构·算法·排序算法
骑着居居追飞机3 小时前
Pandas数据结构
数据结构·pandas
张三xy3 小时前
数据结构 第三章 栈和队列 练习题3.2.4 迷宫求解 C语言代码
c语言·数据结构·算法
X同学的开始3 小时前
数据结构之二叉树的暴力删除
数据结构
misty youth3 小时前
有理数四则运算
c语言·数据结构·算法·c#
程序员波特3 小时前
基础数据结构之数组
java·数据结构·算法·leetcode
¥ 多多¥9 小时前
数据结构:内存的使用
linux·c语言·开发语言·数据结构
小灰灰爱代码9 小时前
C++——将数组a[5]={-1,2,9,-5,7}中小于0的元素置成0。并将其结果输出(要求:用数组名作为函数的参数来实现)
数据结构·c++·算法
liuyang-neu11 小时前
力扣中等 33.搜索旋转排序数组
java·数据结构·算法·leetcode