一、需求
- 给定一个二叉树,判断它是否是高度平衡的二叉树。
-
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
输入:root = [3,9,20,null,null,15,7] 输出:true
二、自顶向下(前序遍历)
2.1 思路分析
- 对于非空树,自顶向下判断所有节点的左右子树高度差与 1 的关系;
- 写一个方法height来返回当前节点的左右子树高度差;
- 在主方法中,根据前序遍历框架,先判断当前根节点的左右子树高度差,然后递归其左子树和右子树;
2.2 代码实现
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null) return true;
int tmp = Math.abs(height(root.left) - height(root.right));
return tmp <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
//该方法求当前节点的高度
private int height(TreeNode node) {
if(node == null) return 0;
return Math.max(height(node.left), height(node.right)) + 1;
}
}
2.3 复杂度分析
- 时间复杂度为
,其中N为二叉树的节点个数,当树为满二叉树,主方法遍历所有的二叉树节点的复杂度为O(N),求节点高度的复杂度为
,故总体复杂度为
,最坏情况下,当树退化为链表时,二叉树的高度为N,故总体时间复杂度为
;
- 空间复杂度为O(N),递归的深度不会超过N;
三、自底向上(后序遍历)
3.1 思路分析
- 上一种方法,自顶向下判断每一个节点,会一个节点会多次重复调用height,增加了时间复杂度;
- 在这里采用自底向上的思想,利用后序遍历框架,对于每个节点只调用一次height,降低了时间复杂度;
3.2 代码实现
class Solution {
public boolean isBalanced(TreeNode root) {
return height(root) != -1;
}
//该方法返回树的高度
private int height(TreeNode node) {
if(node == null) return 0;
//判断左子树是否为平衡树
int left = height(node.left);
if(left == -1) return -1;
//判断右子树是否为平衡树
int right = height(node.right);
if(right == -1) return -1;
//判断以当前节点为根节点的树是否为平衡树
return Math.abs(left - right) < 2 ? Math.max(left, right) + 1 : -1;
}
}
3.3 复杂度分析
- 时间复杂度为O(N),最坏情况下,当树为满二叉树时,需要遍历二叉树的所有节点;
- 空间复杂度为O(N),最坏情况下,当树退化为链表时,递归深度将达到N;
四、学习地址
作者:Krahets