Loading

力扣 - 剑指 Offer 55 - II. 平衡二叉树

题目

剑指 Offer 55 - II. 平衡二叉树

思路1(后序遍历+剪枝)

  • 这题是上一题剑指 Offer 55 - I. 二叉树的深度的进阶,逻辑代码和那个一样,也是后续遍历,获取两个子节点较大的那个深度再加上当前一层返回给父节点,是自底向上的
  • 也为要求是否为平很二叉树,要保证他的左子树和右子树差值不大于1,那么我们就在每次获取左右子树的深度的时候再加一个判断就好啦~
  • 但是我们可以进行剪枝优化,如果不剪枝,就算判定为不是平衡二叉树,那么它还是会递归遍历完。当发现不是平衡二叉树的时候,我们返回 -1 ,然后在每次获取完左右子树节点的深度时候,判断是否等于 -1,这样就可以减少不必要的递归了!

代码

class Solution {
    public boolean isBalanced(TreeNode root) {
        // 只要返回值不是-1,说明就是平衡二叉树
        return dfs(root) != -1;
    }

    public int dfs(TreeNode root) {
        if (root == null) {
            return 0;
        }

        int l = dfs(root.left);
        // 剪枝,返回 -1 说明不是平衡二叉树了
        if (l == -1) {
            return -1;
        }
        int r = dfs(root.right);
        // 同上
        if (r == -1) {
            return -1;
        }

        // 判断左右子树的深度吃的差值是否大于1
        if (Math.abs(l - r) > 1) {
            return -1;
        }

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

复杂度分析

  • 时间复杂度:\(O(N)\)
  • 空间复杂度:\(O(N)\)

思路2(前序遍历)

  • 后序遍历是一种自底向上的方法,只需要遍历一遍链表即可。不过我们也可以使用自顶向下方法,从根节点向下,先判断左右两个子树是否平衡,然后再递归判断子树,不过这样会导致很多节点被重复遍历了,时间复杂度比较高。。

代码

class Solution {
    public boolean isBalanced(TreeNode root) {
        if (root == null) {
            return true;
        }

        // 先判断左右两个子树是否平衡,不平衡的话返回false
        int l = treeDeepth(root.left);
        int r = treeDeepth(root.right);
        if (Math.abs(l - r) > 1) {
            return false;
        }

        // 然后在继续判断他的左右子树是否平衡(前序遍历)
        return isBalanced(root.left) && isBalanced(root.right);
    }

    public int treeDeepth(TreeNode root) {
        if (root == null) {
            return 0;
        }

        int l = treeDeepth(root.left);
        int r = treeDeepth(root.right);

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

复杂度分析

  • 时间复杂度:\(O(N^2)\)
  • 空间复杂度:\(O(N)\)
posted @ 2021-11-24 22:51  linzeliang  阅读(50)  评论(0编辑  收藏  举报