一、需求
- 输入一棵二叉树的根节点,判断该树是不是平衡二叉树。
- 如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false 。
二、前序遍历法
2.1 思路分析
- 上一篇我们求解了关于二叉树的最大深度,基于此原理,在这里求二叉树任意节点的深度;
- 根据前序遍历原理,先判断当前节点的左、右子树的深度是否满足平衡二叉树要求,然后递归判断当前节点的左子树,当前节点的右子树;
2.2 代码实现
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null) return true;
//判断当前节点、当前节点左子树、当前节点右子树是否平衡
int res = Math.abs(depth(root.left) - depth(root.right));
return res <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
//求任意一个节点的深度
public int depth(TreeNode node) {
if(node == null) return 0;
return Math.max(depth(node.left), depth(node.right)) + 1;
}
}
2.3 复杂度分析
- 时间复杂度为
,N为二叉树的节点个数,判断是否为平衡二叉树需遍历所有节点;
- 最坏情况下为满二叉树,计算其深度的时间复杂度为O(N),N为满二叉树的节点个数;
- 第一层计算根节点root深度需计算N次,第二层计算root.left和root.right各需计算(N-1)/2次,依次类推,到最后一层需计算(N+1)/2次,这样每一层最少计算(N+1)/2次,最多计算N次;
- 故总的时间复杂度是层数*每一层的复杂度,即为
;
- 空间复杂度为
,最差情况下,当树退化为链表时,递归需要使用O(N)的栈空间;
三、后序遍历法1
3.1 思路分析
- 上述方法中要遍历每一个节点,然后计算当前节点左子树的深度和右子树的深度,直到某一节点的深度之差不满足平衡二叉树的条件时返回false,否则遍历所有节点后true;
- 上述方法的缺点在于计算每个节点的深度时,存在大量的重复计算,比如计算根节点的深度需要计算左子树和右子树的深度,若根节点符合条件,那么又要重新计算左子树深度;
- 为了克服上述缺点,利用后序遍历,从底向上判断,将每次计算的left和right节点深度的最大值通过加1返回到上一层节点,这样避免重复计算;
3.2 代码实现
class Solution {
public boolean isBalanced(TreeNode root) {
return recur(root) != -1;
}
//规定非平衡二叉树时,返回-1
public int recur(TreeNode root) {
if(root == null) return 0;
int left = recur(root.left);
//若左子树就不是平衡二叉树,直接返回
if(left == -1) return -1;
int right = recur(root.right);
//若右子树不是平衡二叉树
if(right == -1) return -1;
//若当前节点下是平衡二叉树,那么返回当前节点的深度,作为上一层的left或right
//不是平衡二叉树则返回-1
return Math.abs(left-right) <= 1 ? Math.max(left,right) + 1 : -1;
}
}
四、后序遍历法2
4.1 思路分析
- 这是按照第一种方法思路写的,第一种是前序遍历,这里使用后序遍历,时间复杂度和空间复杂度与方法一相同,效率贼低;
4.2 代码实现
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null) return true;
boolean left = isBalanced(root.left);
boolean right = isBalanced(root.right);
boolean res = Math.abs(depth(root.left) - depth(root.right)) <= 1 ? true : false;
return left && right && res;
}
//求任意一个节点的深度
public int depth(TreeNode node) {
if(node == null) return 0;
return Math.max(depth(node.left), depth(node.right)) + 1;
}
}
五、学习地址
作者:Krahets