4.1问题:
实现一个函数,检查二叉树是否平衡。在这个问题中,平衡树的定义如下:任意一个结点,其两棵子树的高度差不超过1.
思考:
可以直接递归访问整颗树,计算每个结点的两棵子树的高度。
public static int getHeight(Node root){ //获取二叉树的深度
if(root == null){
return 0;//终止条件
}
return Math.max(getHeight(root.leftChild),getHeight(root.rightChild))+1;
}
public static boolean isBalance(Node root){
if(root == null){
return true;//终止条件
}
int heighDiff= getHeight(root.leftChild)-getHeight(root.rightChild);
if(Math.abs(heighDiff)>1){
return false;
}
else{
return isBalance(root.leftChild)&&isBalance(root.rightChild);
}
}
虽然可行,但效率不高,这段代码会递归访问每个结点的整棵子树。也就是说,getHeight会被反复调用计算同一个结点的高度。因此,这个算法时间复杂度为O(NlogN)。
看下面一段改进的程序:
public static int checkHeight(Node root){
if(root == null){
return 0;//高度为0
}
//检查左子树是否平衡
int leftHeight = checkHeight(root.leftChild);
if(leftHeight == -1){
return -1;//不平衡
}
//检查右子树是否平衡
int rightHeight = checkHeight(root.rightChild);
if(rightHeight == -1){
return -1;//不平衡
}
//检查当前节点是否平衡
int heightDiff = leftHeight - rightHeight;
if(Math.abs(heightDiff) > 1){
return -1;//不平衡
}else{
return Math.max(leftHeight,rightHeight) + 1;
}
}
public static boolean isBalance1(Node root){
if(checkHeight(root) == -1){
return false;
}else{
return true;
}
}
改进过的算法会从根结点递归向下检查每棵子树的高度。我们会通过checkHeight方法,以递归的方式获取每个结点的左右子树的高度。若子树是平衡的,则checkHeight返回-1.checkHeight会立即中断,并返回-1.
这段代码需要的时间复杂度为O(N),空间复杂度为O(H),H为树的高度。