110. 平衡二叉树
一、自顶向下(暴力法)
1、一棵树是平衡二叉树的条件是它的左右子树高度差不超过1,并且左右子树也是平衡二叉树
2、这个定义里面涉及到高度计算的问题,所以需要另外设置函数。
代码实现
var isBalanced = function(root) {
// 对于空节点的判断
if(!root) return true;
// 一棵树是平衡二叉树的条件是它的左右子树高度差不超过1,并且左右子树也是平衡二叉树
if(Math.abs(depth(root.left)-depth(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right)){
return true;
}else{
return false; // 注意针对其他的情况,其他的情况也需要返回值
}
};
var depth = function(node){
// 对于空节点的判断
if(!node) return -1;
// 一个节点的高度是等于左右子树的最大高度+1
return 1 + Math.max(depth(node.left),depth(node.right));
}
复杂度分析:
时间复杂度:O(nlogn),计算 depth 存在大量冗余操作
空间复杂度:O(n)
二、自底向下 – 优化
1、先查看左右子树是否为平衡二叉树,是就返回之间的最大高度,供根节点计算高度
2、然后再通过左右子树的高度差是否>1,以及左右子树是否是平衡二叉树进行判断根节点是否是平衡二叉树。
即从底向下依次去判断二叉树,并且高度只用计算依次,不用重复计算。有点像后序遍历。
var isBalanced = function(root) {
return Balenced(root) != -1
};
// 用一个函数去控制左右子树的返回值,只要返回值不是-1,那么就代表是二叉树.
// 对于左右子树会返回它们的高度,然后去判断和根节点组成的二叉树是否平衡的
var Balenced = function(root){
// 空节点的判断
if(!root) return 0;
// 先得到左右子树的最大高度
let left = Balenced(root.left);
let right = Balenced(root.right);
// 平衡的时候,返回的是高度。所以要定义不平衡的时候
if(Math.abs(left-right) > 1 || left == -1 || right == -1){
return -1
}
// 若左右子树平衡,返回当前树的深度(左右子树的深度最大值 +1 )
return Math.max(left,right)+1
}