题目描述
- 输入一棵二叉树,判断该二叉树是否是平衡二叉树。
- 牛客链接
解题思路
- 这是一道关于二叉树经典套路问题,因为二叉树本身就是用递归定义的,所以关于二叉树的一些算法题大部分可用递归解。大致思路便是:根据题意,写一个递归函数,函数内部对左子树递归,收集信息,对右子树递归,收集信息,然后根据题意将左右子树信息整合,返回该树的信息,这也有点 分治 的思想在里面。
- 要求该树是平衡二叉树,那么必须满足三个条件:
- 左子树是平衡二叉树
- 右子树是平衡二叉树
- 左右子树的高度之差 <= 1
这便体现出了递归的含义,验证本身是否二叉平衡树,需要知道它的左右子树是否是平衡二叉树,所以我们最初的思路是需要定义一个函数 isBalanced,传入该树的根节点,返回该树是否是平衡二叉树,在函数内部对左右子树递归调用自身。
- 但是,二叉搜索树还要求 左右子树的高度之差 <= 1,所以,我们还必须让该函数验证是否平衡二叉树的同时,返回该树的高度。因为是用java实现,没有指针的概念,所以返回两个参数可以有以下两个途径:
- 第二个返回值,作为参数,以数组的形式传递
- 将两个返回值,包装成一个类,返回对象(当然,如果返回值类型相同,可以返回数组)
- 该题还有一种代码更加简洁的方法:
- 是直接对求二叉树的高度的递归函数进行改写,传入树的根节点,递归函数返回该树高度。
- 同样对左右子树递归,求左右子树的高度;然后在整合信息时,如果两树高度之差不是 <= 1或者左子树高度为 -1 或者右子树高度为 -1 ,则将 -1 设为当前树的高度,返回。
经验教训
- 二叉树经典递归套路(分治)
- java如何返回多个值(如何实现指针的作用)
代码实现
- 解法一:
import java.util.*;
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
return isBalanced(root).isB;
}
//isBalanced():判断传入的树是否是平衡二叉树,若是,返回true和树的正确高度;否则,返回false树的高度设为0
public Result isBalanced(TreeNode root) {
//base case:
if(root == null) {
return new Result(true, 0);
}
//递归,收集左子树信息
Result leftRes = isBalanced(root.left);
//如果左子树不是平衡二叉树,直接返回,此时,树的高度定义为什么都可
if (! leftRes.isB) {
return new Result(false, 0);
}
//递归,收集左子树信息
Result rightRes = isBalanced(root.right);
//如果右子树不是平衡二叉树,直接返回,此时,树的高度定义为什么都可
if (! rightRes.isB) {
return new Result(false, 0);
}
//根据题意,整合左右子树信息:
if (Math.abs(leftRes.depth-rightRes.depth) > 1) {
return new Result(false, 0);
}
//满足平衡二叉树的条件,返回true,并将当前树高度设为 左右子树高度最大值+1
return new Result(true, Math.max(leftRes.depth, rightRes.depth) + 1);
}
//将返回结果定义为一个类
class Result {
boolean isB;//该树是否是平衡二叉树
int depth;//该树高度
public Result(boolean isB, int depth) {
this.isB = isB;
this.depth = depth;
}
}
}
- 解法二: 递归函数返回当前树的高度,根据高度判断是否平衡二叉树:
import java.util.*;
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
return treeDepth(root) != -1;
}
//改编自求二叉树的高度,传入一个树的根节点,如果该树是平衡二叉树,返回该树实际高度,否则,返回-1
public int treeDepth(TreeNode root) {
if(root == null) {
return 0;
}
//递归左子树
int leftDepth = treeDepth(root.left);
//如果左子树不是平衡二叉树,那么当前树肯定也不是平衡二叉树,直接返回-1
if (leftDepth == -1) {
return -1;
}
//递归右子树
int rightDepth = treeDepth(root.right);
//如果右子树不是平衡二叉树,或者左右子树高度之差大于1,那么当前树肯定也不是平衡二叉树,直接返回-1
if (rightDepth == -1 || Math.abs(leftDepth - rightDepth) > 1) {
return -1;
}
//是平衡二叉树,返回该树实际高度
return Math.max(leftDepth, rightDepth) + 1;
}
}