110. 平衡二叉树
正题
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 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
解析
判断二叉树的平衡一定是基于计算二叉树深度的。如何求得某个节点开始的深度是解题的核心。所以我们先探讨一下深度优先遍历的原理和方法。
如图,给定一颗二叉树,求该二叉树的深度,应该怎么做呢?
我们可以认为,root节点是第一层,深度为1, root.left 和 root.right 的深度都是2。也就是说如果当前节点有 left 或者 有 right ,那么我们就可以给他的深度 +1。并且二叉树的深度是以最大深度来决定的。
所以我们有了求深度的基本原则:
-
如果该节点没有子节点,那么他的深度就是它本身,就是1
-
如果该节点有子节点,那么深度在1的基础上再 +1
-
如果节点不存在,那么高度就不存在,那么高度就是 + 0
-
最大深度为二叉树深度
不难想到,我们应该使用递归的方式去求深度。
定义获取某节点深度的 getHeight
方法:
var getHeight = function (root) {
if (!root) {
return 0 // root 不存在那么这个节点高度就是 0
}
if (!root.left && !root.right) {
return 1 // 如果该节点没有子节点,那么他的深度就是它本身,就是1
}
// 继续将 左节点和右节点进行递归,求的高度,并且 加上本身自身高度
return Math.max(getHeight(root.left), getHeight(root.right)) + 1
}
实际上也可以从子节点的角度去考虑,假如我们的递归从子节点开始考虑的话,也可以是写成这样的:
var getHeight = function (child) {
if (!child) { // 记住这个 child 是子节点
return 1 // 没有子节点,那深度就是 1
}
return Math.max(getHeight(child.left) , getHeight(child.right)) + 1
}
求得二叉树深度之后,我们可以通过三个条件来判断是否是平衡二叉树了:
-
root 的左节点深度 和 root 右节点深度之差的绝对值 <= 1
-
root 的左节点是也是平衡二叉树
-
root 的右节点也是平衡二叉树
所以我们最终返回的判断条件应该是这样的:
return Math.abs(getHeight(root.left) - getHeight(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right)
最终完整代码:
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {boolean}
*/
var getHeight = function (child) {
if (!child) { // 记住这个 root 是子节点
return 1 // 没有子节点,那深度就是 1
}
return Math.max(getHeight(child.left) , getHeight(child.right)) + 1
}
// 两种方案求 深度都可以
// var getHeight = function (root) {
// if (!root) {
// return 0
// }
// if (!root.left && !root.right) {
// return 1
// }
// return Math.max(getHeight(root.left), getHeight(root.right)) + 1
// }
var isBalanced = function(root) {
if (!root) {
return true
}
return Math.abs(getHeight(root.left) - getHeight(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right)
};
求二叉树深度是一道很基础的算法题,但是要说明白他的原理还是比较难的,只是希望能帮到大家去解决这个问题。