一、题目
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:true
示例 2:
输入:root = [1,2,2,3,3,null,null,4,4]
输出:false
示例 3:
输入:root = []
输出:true
提示:
- 树中的节点数在范围 [0, 5000] 内
- -104 <= Node.val <= 104
二、解决
此树的深度 = Max{左子树深度, 右子树深度} + 1
1、后序遍历+剪枝(从底至顶)
思路:
对二叉树做后序遍历,从底至顶返回子树深度,若判断某子树不是平衡树,则剪枝(不容易第一时间想到),直接向上返回。
算法流程-recur(root)函数:
- 返回值:
- 当节点root 左/右子树的深度差<=1:则返回当前子树的深度,即节点root的左/右子树的深度最大值+1(max(left, right) + 1)
- 当节点root左/右子树的深度差>2:则返回-1,代表了此子树不是平衡树。
- 终止条件:
- 当root为空:说明越过叶节点,因此返回高度0;
- 当左/右子树深度为-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)