【LeetCode】110. 平衡二叉树(同剑指 Offer 55 - II)

一、题目

给定一个二叉树,判断它是否是高度平衡的二叉树。

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

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

示例 1:
1

输入:root = [3,9,20,null,null,15,7]
输出:true

示例 2:
2

输入:root = [1,2,2,3,3,null,null,4,4]
输出:false

示例 3:

输入:root = []
输出:true

提示:

  • 树中的节点数在范围 [0, 5000] 内
  • -104 <= Node.val <= 104

二、解决

此树的深度 = Max{左子树深度, 右子树深度} + 1
1

1、后序遍历+剪枝(从底至顶)

思路:

对二叉树做后序遍历,从底至顶返回子树深度,若判断某子树不是平衡树,则剪枝(不容易第一时间想到),直接向上返回。

算法流程-recur(root)函数:

  • 返回值
  1. 当节点root 左/右子树的深度差<=1:则返回当前子树的深度,即节点root的左/右子树的深度最大值+1(max(left, right) + 1)
  2. 当节点root左/右子树的深度差>2:则返回-1,代表了此子树不是平衡树。
  • 终止条件
  1. 当root为空:说明越过叶节点,因此返回高度0;
  2. 当左/右子树深度为-1:代表左/右子树不是平衡树,因此剪枝,直接返回-1。

isBalanced(root)函数:

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

代码:

class Solution {
    
    
    public boolean isBalanced(TreeNode root) {
    
    
        return recur(root) != -1;
    }

    private int recur(TreeNode root) {
    
    
	    // 1、Current logic
        if (root == null) return 0;
        // 3、Drill down
        int left = recur(root.left);
		// 2、Current logic
        if(left == -1) return -1;
        
        // 3、Drill down
        int right = recur(root.right);
        // 2、Current logic
        if(right == -1) return -1;
        
        return Math.abs(left - right) < 2 ? Math.max(left, right) + 1 : -1;
    }
}

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

2、先序遍历+判断深度(从顶至底)

思路:

构造一个获取当前子树的深度的函数depth(root) (即面试题55-I. 二叉树的深度),通过比较某子树的左右子树深度差abs(depth(root.left) - depth(root.right)) <= 1是否成立,来判断某子树是否是二叉平衡树。若所有子树都平衡,则子树平衡。

更具体的流程就不讲解了,可看参考1。基础好点,可以结合代码注释进行理解。

代码:

  • 版本1:
class Solution {
    
    
    public boolean isBalanced(TreeNode root) {
    
    
	    // 1、Terminator
        if (root == null) return true;
        // 2 && 3、Current logic && Drill down
        return Math.abs(depth(root.left) - depth(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);
    }

    private int depth(TreeNode root) {
    
    
        if (root == null) return 0;
        return Math.max(depth(root.left), depth(root.right)) + 1;
    }
}
  • 版本2:
class Solution {
    
    
    public boolean isBalanced(TreeNode root) {
    
    
        return judge(root);
    }

    public boolean judge(TreeNode root) {
    
    
        if (root == null) return true;
        if (Math.abs(height(root.left)-height(root.right)) > 1) return false;
        else return judge(root.left) && judge(root.right);
    }
    public int height(TreeNode root) {
    
    
        if (root == null) return 0;
        return Math.max(height(root.left), height(root.right)) + 1;
    }
}

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

满二叉树高度复杂度 O ( l o g n ) O(logn) O(logn),各层节点遍历数量为n,(n-1)/2*2,(n-3)/4*4,(n-7)/8*8,...,1*(n+1)/2
总体时间复杂度 = 每层执行复杂度*层数复杂度= O ( n l o g n ) O(nlogn) O(nlogn)

空间复杂度: O ( n ) O(n) O(n)
2

三、参考

1、面试题55 - II. 平衡二叉树(从底至顶、从顶至底,清晰图解)

猜你喜欢

转载自blog.csdn.net/HeavenDan/article/details/110920874