我的LeetCode:https://leetcode-cn.com/u/ituring/
我的LeetCode刷题源码[GitHub]:https://github.com/izhoujie/Algorithmcii
LeetCode 110. 平衡二叉树
题目
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
- 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过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 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/balanced-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
必须验证根和每一个节点的左右子树高度差:
- 自顶向下验证每个节点;(会存在重复计算问题)
- 自底向上验证每个节点,一旦某个子节点不符合即返回,不再计算上层节点;(最多一次计算,最快)
思路1-自顶向下,递归校验
递归计算同层节点左右子树的高度差,存在重复计算;
算法复杂度:
- 时间复杂度: $ {\color{Magenta}{\Omicron\left(nlogn\right)}} $ 计算略复杂:详见复杂度分析
- 空间复杂度: $ {\color{Magenta}{\Omicron\left(n\right)}} $ 递归栈的深度
思路2-自底向上/二叉树的后序遍历,递归校验
与方法1的唯一区别是从叶子节点开始向上校验同层节点的左右子树高度差,一旦发现差超过1的可以直接返回,跳过对上层节点的计算,速度最快;
算法复杂度:
- 时间复杂度: $ {\color{Magenta}{\Omicron\left(n\right)}} $ 每个节点最多访问一次
- 空间复杂度: $ {\color{Magenta}{\Omicron\left(n\right)}} $ 递归栈的深度
算法源码示例
package leetcode;
/**
* @author ZhouJie
* @date 2020年1月11日 下午8:32:42
* @Description: 110. 平衡二叉树
*
*/
public class LeetCode_0110 {
}
// Definition for a binary tree node.
class TreeNode_0110 {
int val;
TreeNode_0110 left;
TreeNode_0110 right;
TreeNode_0110(int x) {
val = x;
}
}
class Solution_0110 {
/**
* @author: ZhouJie
* @date: 2020年5月18日 下午11:54:54
* @param: @param root
* @param: @return
* @return: boolean
* @Description: 1-对根及左右子树递归计算高度差;
*
*/
public boolean isBalanced_1(TreeNode_0110 root) {
// 当前节点为null或者其左右节点的高度差不大于1
return root == null || isBalanced_1(root.left) && isBalanced_1(root.right)
&& Math.abs(maxDepth(root.left) - maxDepth(root.right)) < 2;
}
/**
* @author: ZhouJie
* @date: 2020年5月19日 上午11:54:20
* @param: @param root
* @param: @return
* @return: int
* @Description: 计算树高
*
*/
private int maxDepth(TreeNode_0110 root) {
return root == null ? 0 : Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
/**
* @author: ZhouJie
* @date: 2020年5月18日 下午11:55:37
* @param: @param root
* @param: @return
* @return: boolean
* @Description: 2-后续遍历,自底向上校验每层树的高度差,一旦不平衡直接返回,上层节点不再处理;
*
*/
public boolean isBalanced_2(TreeNode_0110 root) {
return checkBlance(root) != -1;
}
private int checkBlance(TreeNode_0110 root) {
if (root == null) {
return 0;
}
// 递归计算左右子树的高度,若遇到-1代表树已在某一层已经不平衡,无需再递归了,直接返回
int left = checkBlance(root.left);
if (left == -1) {
return -1;
}
int right = checkBlance(root.right);
if (right == -1) {
return -1;
}
// 一旦任意同层左右子树的高度差大于1就直接返回-1,-1会直接返回,相当于剪枝,避免后面无意义的递归
return Math.abs(left - right) > 1 ? -1 : Math.max(left, right) + 1;
}
}