二叉树OJ题

 一、相同的树

两棵树是否相同,有三种情况。1、两棵树都为空 2、两棵树有一颗为空 3、两棵树都不为空

1情况下相同,2情况下不相同,3情况下需要进一步讨论

3情况下,比较根节点的值,不相同返回false,相同则递归调用isSameTree检验左右子树。

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if(p == NULL && q == NULL)
    {
        return true;
    }

    if(p == NULL || q == NULL)
    {
        return false;
    }

    if(p->val != q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

二、二叉树的前序遍历

 这个题看上去很简单,但是要做的准备工作很多。

int* preorderTraversal(struct TreeNode* root, int* returnSize) {

}

首先观察题目给的函数参数中, int* returnSize 其实是向我们要输出节点数。而这个题目没有给出具体的二叉树,我们不知道有多少个节点,所以写一个函数求二叉树节点个数。

 int BTreeSize(struct TreeNode* root)
 {
    return root == NULL ? 0 : BTreeSize(root->left) + BTreeSize(root->right) + 1;
 }

 其次,给定函数的参数显然不适宜递归使用,所以另外创建一个函数,用递归的方法前序遍历

void _preorder(struct TreeNode* root,int* a,int* p)
{
    if(root == NULL)
    {
        return;
    }

    a[(*p)++] = root->val;
    
    _preorder(root->left,a,p);
    _preorder(root->right,a,p);
}

需要注意的是,给定函数最后需要返回一个指针,所以malloc一个数组用于存储二叉树节点值;

为了按照我们的需求访问下标,这里一定采用传值调用,否则会带来很多麻烦。

最后的代码

 int BTreeSize(struct TreeNode* root)
 {
    return root == NULL ? 0 : BTreeSize(root->left) + BTreeSize(root->right) + 1;
 }

void _preorder(struct TreeNode* root,int* a,int* p)
{
    if(root == NULL)
    {
        return;
    }

    a[(*p)++] = root->val;
    
    _preorder(root->left,a,p);
    _preorder(root->right,a,p);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    *returnSize = BTreeSize(root);
    int* a = (int*)malloc(sizeof(int) * (*returnSize));
    int i = 0;
    _preorder(root,a,&i);
    return a;
}

三、翻转二叉树

 后序递归遍历

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;
}

四、对称二叉树

这道题只需要遍历左右子树,所以另分装一个函数,参数为左右子树。

bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{

}

 左右子树的情况分三种:1、左右子树都为空 2、左右子树有一个为空 3、左右子树都不为空

1情况下对称,2情况下不对称,3情况下还需进一步比较两个节点的值

bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
    if(left == NULL && right == NULL)
    return true;
    if(left == NULL || right == NULL)
    return false;

    if(left->val != right->val)
    return false;
    return _isSymmetric(left->left,right->right) && _isSymmetric(left->right,right->left);
}

最后的代码

bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
    if(left == NULL && right == NULL)
    return true;
    if(left == NULL || right == NULL)
    return false;

    if(left->val != right->val)
    return false;
    return _isSymmetric(left->left,right->right) && _isSymmetric(left->right,right->left);
}

bool isSymmetric(struct TreeNode* root) {
    return _isSymmetric(root->left,root->right);
}

五、另一颗树的子树

 root任何一个非空子树都有可能,所以遍历root所有子树,与subroot进行比较,自己也是自己的子树。

同时注意给出的范围,不需要考虑空节点。

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

    if(isSameTree(root,subRoot))
        return true;

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

 

这里会用到之前判断树是否相同的函数

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if(p == NULL && q == NULL)
    {
        return true;
    }

    if(p == NULL || q == NULL)
    {
        return false;
    }

    if(p->val != q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

六、平衡二叉树

 平衡二叉树:所有节点的左右子树的深度相差不超过1.

首先分装一个求深度的函数

 int BTreeHeight(struct TreeNode* root)
 {
    if(root == NULL)
    return 0;
    
	int leftheight = BTreeHeight(root->left);
	int rightheight = BTreeHeight(root->right);
	return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
 }

 相当于一个前序遍历,递归求得结果

bool isBalanced(struct TreeNode* root) {
    if(root == NULL)
        return true;
    if(abs(BTreeHeight(root->left) - BTreeHeight(root->right)) > 1)
        return false;
    
    return isBalanced(root->left) && isBalanced(root->right);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值