记录 1 道算法题
平衡二叉树
如果左子树的高度和右子树的高度相差超过 1,就返回 false。
空树 返回 true。
高度是什么呢,就是左节点一直到他的最深的left节点的层数差。
a
b
c d
f
e
a 的高度 就是 a 到 最底层 e 的层数 5
b 的高度 就是 b 到 最底层 e 的层数 4
d 的高度 则是 0, 因为 d 就是叶子节点了。
c 的高度 是 3
以此类推
f 的没有左节点,所以他的左节点高度是 0 , 右节点高度是 1, 他们相差1 所以合理。
c 的左节点没有,所以是 0 但是右节点 f 的高度是 2,所以 不合理。
解题前先介绍一下计算树的高度的做法,计算树的高度用到了累加的办法。
function count(root) {
// 叶子节点的虚空子节点
if (!root) return 0
// 递归会获得从底层一直累加上来的高度
const left = root(root.left)
const right = root(root.right)
// 高度采用 左节点和右节点之间最高的那个,即最深的。
// 然后加1,是加上自己,实现累加。
return Math.max(left, right) + 1
}
有时候递归容易想复杂,其实可以抛开很多东西,就光看,我们知道了某个父节点的左节点的高度和右节点的高度,那么我们就可以知道他们的高度差,所以是Math.abs(left - right) 有没有超过 1。
再做一个优化就是我们可以让他提早返回,因为一旦有一个地方高度差不合格,那整棵树就不是平衡二叉树了。所以我们用一个小于0或者其他非 0-n数字的东西做额外标记,如果哪一层不合理就之间抛出来,外层的递归就会拿得到,如果里面抛了,外层之间抛。这样可以提早返回。
function isBalanced(root) {
// 处理空树
if (!root) return true
function f(node) {
// 和上面计算高度一样
if (!node) return 0
const left = f(node.left)
// -1 作为标记
if (left < 0) return -1
const right = f(node.right)
if (right < 0) return -1
// 在返回树的高度之前拦截判断一下,如果高度差不合格就之间返回了。
// 源头的不合理判断抛出
if (Math.abs(left - right) > 1) {
return -1
}
// 正常则继续累加高度
return Math.max(left, right) + 1
}
return f(root) >= 0
}
结束