39、平衡二叉树

解题思路

这道题目其实跟二叉树的深度这道题用到的方法是一样的,为什么说是一样的呢?因为我们求二叉树的深度,其实就是求了左右子树的深度的最大值,但是这道题目是要让我们判断二叉树是不是平衡树。

我们都知道如何判断一棵二叉树是不是平衡二叉树,就是它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

所以,这个时候我们只需要判断左右子树的深度之差有没有超过1,若超过了则不是平衡的,反之则为平衡二叉树。

我们先来回顾一下求二叉树深度的代码:

public int TreeDepth(TreeNode root) {
        if(root == null)
            return 0;
        int l = TreeDepth(root.left);
        int r = TreeDepth(root.right);
        return Math.max(l,r)+1;
    }

我们只需要在上面的代码加上判断左右子树的深度之差即可。

(左子树深度-右子树深度) > 1,不是平衡树

所以代码可以改为:

    boolean isBalanced = true; // 默认标记为true
    public boolean IsBalanced_Solution(TreeNode root) {
        TreeDepth(root);
        return isBalanced;
    }

public int TreeDepth(TreeNode root) {
        if(root == null)
            return 0; // 递归终止
        int l = TreeDepth(root.left);
        int r = TreeDepth(root.right);

        if(Math.abs(l-r) > 1){
            isBalanced = false;  // 不是平衡树
        }

        return Math.max(l,r)+1; // 求深度
    }

但是,上面的代码总是遍历完全部的节点,我们想想,如果一判断到左右子树的深度之差大于1,即这个二叉树就不可能再是平衡树了。

所以,我们还可以对上面代码进行优化。

进行剪枝:当判断到左右子树的深度之差大于1的时候,则返回-1。每次递归结束判断返回值是否-1,若为-1,则立即返回。

所以优化后的代码为:

    boolean isBalanced = true;
    public boolean IsBalanced_Solution(TreeNode root) {
        TreeDepth(root);
        return isBalanced;
    }

public int TreeDepth(TreeNode root) {
        if(root == null)
            return 0;
        int l = TreeDepth(root.left);
        if(l == -1)  return -1;  // 提前返回
        int r = TreeDepth(root.right);
        if(r == -1)  return -1;  // 提前返回
         if(Math.abs(l-r) > 1){
            isBalanced = false;  // 不是平衡树
            return -1;  // 加一个标记-1,已经不可能是平衡树了
        }

        return Math.max(l,r)+1;
    }

看一下整体动态图:

39

复杂度分析:

时间复杂度:O(N)。N为树的节点个数。最差情况下需要遍历所有节点。

空间复杂度:O(N)。若树退化成了链表,则递归深度为节点的个数,需要用到O(N)的栈空间。