剑指Offer55-Ⅱ—平衡二叉树

剑指Offer55-Ⅱ

题意

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

解法1—后序遍历(左右根)+剪枝,从底至顶

对二叉树做后序遍历(即左右根的遍历顺序),从底至顶返回子树的深度,若判定某子树不是平衡树则 “剪枝” ,直接向上返回。

算法流程

recur(root) 函数:

  • 返回值:
  1. 当节点root 左 / 右子树的深度差 ≤1 :则返回当前子树的深度,即节点 root 的左 / 右子树的深度最大值 +1 ( max(left, right) + 1 );
  2. 当节点root 左 / 右子树的深度差 >1 :则返回 −1 ,代表 此子树不是平衡树 。
  • 终止条件:

  1. 当 root 为空:说明越过叶节点,因此返回高度 0 ;
  2. 当左(右)子树深度为 −1 :代表此树的 左(右)子树 不是平衡树,因此剪枝,直接返回 -1 ,就没必要继续往下执行了。

isBalanced(root) 函数:

  • 返回值: 若 recur(root) != -1 ,则说明此树平衡,返回 true ; 否则返回 false 。

C++实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution 
{
public:
    int recur(TreeNode* root)
    {
        // 如果root为空,说明越过叶子节点,返回高度0
        if(NULL==root)
            return 0;
        int left = recur(root->left);//递归左子树,求左子树高度
        if(-1==left)    // 如果root的左子树不是平衡树,就进行剪枝,直接返回-1,没必要再往下执行了
            return -1;

        int right = recur(root->right);//递归右子树,求右子树高度
        if(-1==right)
            return -1;  // 如果root的右子树不是平衡树,就进行剪枝,直接返回-1,没必要再往下执行了 

        if(abs(left-right)>1)//如果左右子树高度相差大于1,就代表此树不是平衡树,直接返回-1
            return -1;
        else
            return max(left,right)+1;   //否则,返回root为根节点的树的高度
    }
    bool isBalanced(TreeNode* root) 
    {
        if(NULL==root)
            return true;
        return recur(root)!=-1;
    }
};

法2—前序遍历(根左右)+判断深度,从顶至底

  1. 先构造一个获取当前子树的深度的函数 depth(root);
  2. 然后,通过比较某子树的左右子树的深度差 abs(depth(root.left) - depth(root.right)) <= 1 是否成立,来判断某子树是否是二叉平衡树。
  3. 再判断该子树的左右子树是否平衡,若所有子树都平衡,则此树平衡。

C++实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution 
{
public:
    int recur(TreeNode* root)
    {
        // 如果root为空,说明越过叶子节点,返回高度0
        if(NULL==root)
            return 0;
        int left = recur(root->left);//递归左子树,求左子树高度
        if(-1==left)    // 如果root的左子树不是平衡树,就进行剪枝,直接返回-1,没必要再往下执行了
            return -1;

        int right = recur(root->right);//递归右子树,求右子树高度
        if(-1==right)
            return -1;  // 如果root的右子树不是平衡树,就进行剪枝,直接返回-1,没必要再往下执行了 

        if(abs(left-right)>1)//如果左右子树高度相差大于1,就代表此树不是平衡树,直接返回-1
            return -1;
        else
            return max(left,right)+1;   //否则,返回root为根节点的树的高度
    }
    int depth(TreeNode* root)
    {
        if(NULL==root)
            return 0;
        int left_depth = depth(root->left);
        int right_depth = depth(root->right);
        return max(left_depth,right_depth)+1;
    }
    bool isBalanced(TreeNode* root) 
    {
        if(NULL==root)
            return true;

        // 法1
        // return recur(root)!=-1;

        //法2
        int left_depth = depth(root->left); //该树左子树高度
        int right_depth=depth(root->right); //该树右子树高度
        bool flag = abs(left_depth-right_depth)<=1; //该树左右子树差是否≤1
        bool left_tree_balance = isBalanced(root->left); //该树左子树是不是平衡二叉树
        bool right_tree_balance = isBalanced(root->right); //该树右子树是不是平衡二叉树
        return flag&&left_tree_balance&&right_tree_balance;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心之所向便是光v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值