数据结构:二叉树OJ题

目录

前言 

一、单值二叉树

二、相同的树

三、另一颗树的子树

四、翻转二叉树

五、平衡二叉树


前言 

    前面讲了很多关于二叉树的知识,再来几道二叉树的OJ题练手,加深印象的同时,能让我们更好的理解二叉树。

Definition for a binary tree node.
 struct TreeNode
 {
     int val;
     struct TreeNode *left;
     struct TreeNode *right;
 };

每道题都给了这个结构体,这里放出来就不没每道题都放上这个代码了 。

一、单值二叉树

题目链接(单值二叉树

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

只有给定的树是单值二叉树时,才返回 true;否则返回 false。

就是判断一个二叉树上的节点的值是否都相同

bool isUnivalTree(struct TreeNode* root) {
    if(root==NULL)
    return true;
    if(root->left&&root->left->val!=root->val)
    return false;
    if(root->right&&root->right->val!=root->val)
    return false;
    return isUnivalTree(root->left)&&isUnivalTree(root->right);
}

    这里注意一下,在这道题里,空树也算是单值二叉树,然后通过遍历二叉树判断每个节点的值是否相同,这是一道很基础的题目。

二、相同的树

题目链接(相同的树) 

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1


输入:p = [1,2,3], q = [1,2,3]
输出:true
示例 2


输入:p = [1,2], q = [1,null,2]
输出:false

bool isSameTree(struct TreeNode* p, struct TreeNode* q) 
{
    if(p==NULL)
    {
        if(q==NULL)
        return true;
        if(q!=NULL)
        return false;
    }
    if(q==NULL)
    {
        if(p==NULL)
        return true;
        if(p!=NULL)
        return false;
    }
    if(q->val==p->val)
    return isSameTree(q->left,p->left)&&isSameTree(q->right,p->right);
    else
    return false;
}

    如果有一个树为空树,另一个树不为空树那肯定是不同的,反之则相同, 然后通过递归,同时遍历两个树,并进行节点值的比较,从而可以判断出两个树是否相同。

   这里有一道和这个类似的题目,可以练练手(对称二叉树),这里就给个思路。

思路:可以将左右子树看成需要比较的两个树,这道题就又回到了判断相同二叉树上,不过有些细节还是需要注意一下。

三、另一颗树的子树

题目链接(另一颗数的子树

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

示例 1


输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true
示例 2


输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
 {
    if(p==NULL)
    {
        if(q==NULL)
        return true;
        if(q!=NULL)
        return false;
    }
    if(q==NULL)
    {
        if(p==NULL)
        return true;
        if(p!=NULL)
        return false;
    }
    if(q->val==p->val)
    return isSameTree(q->left,p->left)&&isSameTree(q->right,p->right);
    else
    return false;
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    if(root==NULL||subRoot==NULL)
    return false;
    if(isSameTree(root,subRoot))
    return true;

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

     判断是否为另一个树的子树,需要用到前面的判断相同二叉树的代码这里就直接拿过来放在这里了,通过遍历从每个节点开始判断是否有与其根节点相同的节点,找到一个相同值的节点,就医这个节点为根节点用到前面判断两个二叉树相同的函数,开始判断,相同的话就没啥问题了,不同就还要继续寻找。

四、翻转二叉树

题目链接(翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

输入:root = [2,1,3]
输出:[2,3,1]

示例 3:

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

 根据题意就是需要把一个二叉树左右子树对称位置节点的值交换。

struct TreeNode* invertTree(struct TreeNode* root) {
    if(root==NULL)
    return NULL;
    struct TreeNode*left=invertTree(root->left);
    struct TreeNode*right=invertTree(root->right);
    root->left=right;
    root->right=left;
    return root;
}

    从根节点开始,递归地对二叉树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。

五、平衡二叉树

题目链接(平衡二叉树

给定一个二叉树,判断它是否是 平衡二叉树

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:true

示例 2:

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

示例 3:

输入:root = []
输出:true

    这道题中的平衡二叉树的定义是:二叉树的每个节点的左右子树的高度差的绝对值不超过 1,则二叉树是平衡二叉树。 

int depth(struct TreeNode* root)
{
    if(root==NULL)
    return 0;
    int l=depth(root->left);
    int r=depth(root->right);
    if(l>r)
    return l+1;
    return r+1;
}
bool isBalanced(struct TreeNode* root) {
    if(root==NULL)
    return true;
    int left=depth(root->left);
    int right=depth(root->right);
    if(abs(left-right)>1)
    return false;
    return isBalanced(root->left)&&isBalanced(root->right);
}

    写一个计算二叉树高度的函数,再算出左右子树的高度差,超过1就return false,通过递归的方式把每个节点的左右子树的高度都计算并进行比较,直到把每个左右子树比较完。


     分享的二叉树OJ题就这些了,每道题都给了链接,可以自己去练练手,希望对各位有帮助。

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值