1. 问题描述:
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过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
2. 思路分析:
① 题目其实还是比较好理解的,我们需要做的是判断出所有节点的左右子树的高度是否满足高度差小于等于1的条件即可,只有当所有的节点都满足条件才称为是平衡二叉树,所以我们需要计算出当前节点的左右子树的高度,在计算节点高度的时候我们可以使用递归的方法,根据递归层层返回的特点由下往上进行高度的求解即可,我之前是新建了一个与领扣中方法名字一样的内部类TreeNode,里面除了左右节点的属性之外还添加了一个当前节点高度的属性用来记录当前节点的高度但是在提交上去之后发现会报错,好像不可以使用与方法中同名的节点,所以我把节点的高度存储在了节点的val变量上,主要是这个变量目前还没有用所以可以这样使用,但是在测试的时候最好使用另外一个变量
② 在写递归的代码的时候不妨画一下二叉树的图这样对于细节的处理与出口的设计会有帮助,比如下面的一棵二叉树,在计算节点的高度的时候由于使用的是递归会一直走到最低端直到没有子树了,比如一开始的时候回走ABD,到D的时候往下递归发现D的左子树和右子树都为空,当为空树的时候也即在出口的时候应该返回零,返回到D这一层的时候应该是D的左右子树的最大值并且加上D这一节点的1个高度,因为D的左右子树都为零那么D的高度就为1,在计算节点返回的过程中会将当前的节点的高度层层返回最终到达根节点,因为是递归求解所以最终会计算出所有节点的高度,其实在画出这一棵二叉树之后那么还是比较好写出递归代码来的,并且为了方便我们使用一个全局变量来记录递归过程中是否存在某些子树不满足高度差小于等于1的条件,当出现了不满足的条件那么修改标志的全局变量即可,在计算节点高度的过程中就可以判断是否满足条件了,所以最终可以根据全局变量的值即可判断是否是平衡二叉树
③ 看了领口的题解之后发现它是分自上而下进行递归与自下而上进行递归的方法,而我的代码则是在递归往下的时候计算子树的高度层层往上返回高度的,所以应该属于自下而上进行递归计算的
官方的第一种自上而下的递归主要是使用了一个方法来计算节点的高度,并且在计算高度的时候是自上而下计算的,所以从根节点往下计算过程中存在着重复计算子树的高度,每一次都是从上往下进行计算,所以来说效率不高,第二种方法是使用一个类来记录当前节点下的子树是否平衡,思路是在递归往下返回的过程中逐一创建每一个节点,计算出当前节点下的左右子树的高度来创建出当前节点,节点中存在着一个记录当前节点是否平衡的标志,最后递归结束会创建出根节点,这个时候判断创建的根节点的记录是否平衡的值即可知道是否是平衡二叉树即可,对于第二种思路还是值得学习的
3. 代码如下:
我自己写的:
public class Solution {
int flag = 1;
public boolean isBalanced(TreeNode root) {
recrusion(root);
return flag == 1;
}
/*计算所有节点的高度, 在写代码的时候画出二叉树会比较好理解在画的时候就可以写出出口以及其他的细节
* 这里设置一个标志来看一下中间是否存在不满足条件的节点
* */
public int recrusion(TreeNode root) {
/*注意是返回0*/
if (root == null) return 0;
int left = recrusion(root.left);
int right = recrusion(root.right);
/*当前节点的高度就为左右子树的高度的最大值加上1, 并且直接返回高度即可*/
if (Math.abs(left - right) > 1) flag = 0;
return root.val = Math.max(left, right) + 1;
}
}
自上而下递归:
class Solution {
private int height(TreeNode root) {
if (root == null) {
return -1;
}
return 1 + Math.max(height(root.left), height(root.right));
}
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
return Math.abs(height(root.left) - height(root.right)) < 2
&& isBalanced(root.left)
&& isBalanced(root.right);
}
}
自下而上递归:
final class TreeInfo {
public final int height;
public final boolean balanced;
public TreeInfo(int height, boolean balanced) {
this.height = height;
this.balanced = balanced;
}
}
class Solution {
private TreeInfo isBalancedTreeHelper(TreeNode root) {
if (root == null) {
return new TreeInfo(-1, true);
}
TreeInfo left = isBalancedTreeHelper(root.left);
if (!left.balanced) {
return new TreeInfo(-1, false);
}
TreeInfo right = isBalancedTreeHelper(root.right);
if (!right.balanced) {
return new TreeInfo(-1, false);
}
if (Math.abs(left.height - right.height) < 2) {
return new TreeInfo(Math.max(left.height, right.height) + 1, true);
}
return new TreeInfo(-1, false);
}
public boolean isBalanced(TreeNode root) {
return isBalancedTreeHelper(root).balanced;
}
}