平衡二叉树:它是一棵空树或者左右子树的高度差绝对值不超过1,并且左右两棵子树都是平衡二叉树。
要判断一棵树是否是平衡二叉树,由其定义我们很容易想到通过计算出左右两棵子树的高度及其高度差来进行判断。
首先,判断当前节点是否是平衡二叉树,则需要开始遍历整棵树,求其左右子树的高度。递归判断其左右子树是否为平衡二叉树,又一次需要遍历其子树求其高度。多次求其高度,越接近叶子节点的节点高度被求的次数越多。
这种方法很容易理解,但是它的时间复杂度是O(N*N),这是一种十分低效的算法。后面我们会贴出代码。
既然导致低效的原因是因为多次求了节点的高度,因此,考虑将高度放在参数列表中,在递归的过程中返回给上一层。
也就是说,从叶子节点开始判断这棵树是否是平衡二叉树。
时间复杂度是O(N)
package erchashu_bianli;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author zhengchao
*/
public class PinghengErchashu {
private final int[] array = { 1,2,3,4,5,6};
private static List<Node> nodeList = null;
//我们构建一个左拐二叉树的数据结构,假设节点数大于2,否则肯定是平衡二叉树。
public void createErChaTree() {
nodeList = new ArrayList<>();
// 将一个数组的值依次转换为Node节点
for (int nodeIndex = 0; nodeIndex < array.length; nodeIndex++) {
nodeList.add(new Node(array[nodeIndex]));
}
// 对前lastParentIndex-1个父节点按照父节点与孩子节点的数字关系建立二叉树
for (int parentIndex = 0; parentIndex < array.length - 2; parentIndex++) {
// 左孩子
nodeList.get(parentIndex).left = nodeList.get(parentIndex + 1);
}
nodeList.get(array.length - 2).left = nodeList.get(array.length - 1);
}
public static void main(String[] args){
PinghengErchashu pingheng = new PinghengErchashu();
pingheng.createErChaTree();
Node root = nodeList.get(0);
boolean isBalance = isBalance(root);
System.out.println("是否是平衡二叉树:"+isBalance);
}
public static boolean isBalance(Node head){
boolean[] res = new boolean[1];
res[0] = true;
getHeight(head,1,res);
return res[0];
}
public static int getHeight(Node head ,int level, boolean[] res){
if(head == null){
return level;
}
int lH = getHeight(head.left,level+1,res);
if(!res[0]){
return level;
}
int rH = getHeight(head.right,level+1,res);
if(!res[0]){
return level;
}
if(Math.abs(lH-rH)>1){
res[0] = false;
}
return Math.max(lH, rH);
}
}
在构建二叉树时,我们特意构造了一个非平衡二叉树。
运行结果:
run:
是否是平衡二叉树:false
成功构建 (总时间: 0 秒)
private final int[] array = { 1,2,3,4,5,6};
变成
private final int[] array = { 1,2};
运行结果:
run:
是否是平衡二叉树:true
成功构建 (总时间: 0 秒)