判断是否为平衡二叉树?

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1

从顶至底(暴力法):

     暴力法的思想就是求出左右子树的高度,然后比较左子树的高度和右子树的高度是否符合题意,如果符合,再去判断左子树和右子树是否为平衡二叉树。此法复杂度较高,因为是从顶到底调用求高度函数,其实在求root节点高度时,整个树的高度已经计算出来了但并未保存,每次调用都会带来求此节点为根的子树的重复操作。

height函数用来求节点的高度。

isbalanced函数用来判断以该节点为根的子树是否为平衡二叉树。

int height(TreeNode* root){
    if(!root)return 0;
    return max(height(root->left),height(root->right))+1; // 根节点的高度 = 左子树和右子树高度的较大值+1
}

bool isBalanced(TreeNode* root){
    if(!root)return true;
    int h1 = height(root->left),h2 = height(root->right);
    return abs(h1-h2) <= 1 && isBalanced(root->left) && isBalanced(root->right);

    // 判断左子树和右子树的高度是否符合平衡二叉树 并且 左右子树是否为平衡二叉树  三者皆为true 以root为根的子树为平衡二叉树
}

时间复杂度为O(nlogn)。

 

 

 

从底至顶(提前阻断):

思路 就是利用二叉树的后序遍历来做该题。

二叉树的常用遍历方法一共有四种:

前序遍历:先访问根节点,然后访问左子树,最后访问右子树。

中序遍历:先访问左子树,然后访问根节点,最后访问右子树。

后序遍历:先访问左子树,然后访问右子树,最后访问根节点。

层序遍历:从上到下,从左至右访问某一层的节点。

思考: 使用自底向上改用什么遍历来解决该问题。首先排除到前序遍历和层序遍历 因为它们都是自上而下进行访问的。

再看中序遍历,先左子树,在根节点。 若此时访问到根节点,无法知道右子树的高度,无法解决此问题。所以采用后序遍历。

思路:先通过遍历左子树到达最左端,在调用一次访问空节点,此时返回高度0;再去遍历该节点右子树的根节点,通过后序遍历可以得知该节点右子树的高度,此时对高度进行判断是否符合平衡二叉树的要求,再更新该节点的高度即可。

第一版本:

bool balanced(TreeNode* root,int &height){// 相对于前面的方法加了高度的参数
         if(!root){
        height = 0;
        return true;
    }
    bool b1,b2;
    int h1,h2;
    b1 = balanced(root->left,h1);
    b2 = balanced(root->right,h2);// 后序遍历
    height = max(h1,h2)+1;// 更新该节点高度
    return b1 &&b2 &&abs(h1-h2) <2;
    }
    bool isBalanced(TreeNode* root) {
        int h = 0; // 这里必须声明一个变量,因为我使用了引用 直接调用 balanced(root,0)会报错。
        return balanced(root,h);
    }

 

 

第二版本:

int balanced(TreeNode* root){//相对于第一版本 我用返回值int为该节点的高度值 采用-1表示该节点所在的子树不为平衡二叉树 0表示空节点
    if(!root)return 0;
    int h1 = balanced(root->left);
    int h2 = balanced(root->right);
    if(h1 == -1 || h2 == -1 || abs(h2-h1) > 1)return -1;// 如果左右子树有不为平衡二叉树的 高度差大于一则返回-1 表示该树已经不为平衡二叉树了 直接返回-1即可 不需要多余判断。
    return max(h1,h2) +1; // 返回根节点的高度

    }
    bool isBalanced(TreeNode* root){
        return balanced(root) != -1; // 如果根节点的值为-1 表示不为平衡二叉树 返回false 如果不为-1,则为root的高度 返回true即可
    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值