题目描述:
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
输入:
第一行输入有n,n表示结点数,结点号从1到n。根结点为1。 n <= 10。
接下来有n行,每行有两个个整型a和b,表示第i个节点的左右孩子孩子。a为左孩子,b为右孩子。当a为-1时,没有左孩子。当b为-1时,没有右孩子。
输出:
输出一个整型,表示树的深度。
样例输入:
3
2 3
-1 -1
-1 -1
样例输出:
2
本题求二叉树的深度,可以用递归来实现。如果根节点只有左子树,那么高度则为左子树的高度+1;如果根节点只有右子树,那么高度则为右子树的高度+1;若根节点左右子树都存在,那么高度则为左右子树中高度较大的那一个+1。如此依次类推下去。代码如下:
//二叉树
class TreeNode{
int value;
TreeNode right = null;
TreeNode left = null;
TreeNode(int value){
this.value = value;
this.left = this.right = null;
}
}
//获得一颗二叉树的深度
public static int getTreeDepth(TreeNode root){
if(root==null)
return 0;
int left = getTreeDepth(root.left);
int right = getTreeDepth(root.right);
return left>right?left+1:right+1;
}
那么,问题来了。如果想要判定这颗树是否是平衡二叉树呢?
一种比较直接的方法是,遍历整棵树,获得每个节点的左右孩子节点的高度,若没有左或右孩子节点,可以看做其左右的孩子节点为0。然后比较孩子节点的高度之差,若高度之差的绝对值是小于1的,则认为这个这个节点的左右子树是平衡的。可以如下表示出来:
//判断一颗树是否是平衡二叉树
public static boolean isBalance(TreeNode root){
if(root==null)
return true;
int left = getTreeDepth(root.left);
int right = getTreeDepth(root.right);
int diff = left-right;
if(diff>1||diff<-1){
return false;
}
return isBalance(root.left)&&isBalance(root.right);
}
写到此处,会发现这种方法,在遍历是会存在大量的重复。例如在判定根节点是否是平衡的过程中,我们会调用getTreeDepth函数,输入左子树的根节点2,依次遍历4,5,7;然后在判断节点2的时候,又要遍历4,5,7,所以会存在很多的重复。
我们会想到二叉树的后续遍历方式,就是先判定左右子树是,在遍历到节点之前,我们已经遍历到了它的左右子树,并将左右子树的高度记录下来,我们就可以一边遍历,一边判定每个节点是不是平衡的了。于是,就有了以下代码:
//保存节点的高度
class Depth{
int depth;
}
//后序遍历的方式遍历二叉树的每一个结点,在遍历到一个结点之前我们已经遍历了它的左右子树
public static boolean isBalanced(TreeNode root,Depth de){
if(root==null){
de.depth = 0;
return true;
}
Depth left = new Depth();
Depth right = new Depth();
if(isBalanced(root.left,left)&&isBalanced(root.right,right)){
int leftDep = left.depth;
int rightDep = right.depth;
int diff=leftDep-rightDep;
if(diff<=1 && diff>=-1){
de.depth = leftDep>rightDep?leftDep+1:rightDep+1;
return true;
}
}
return false;
}
已经AC完整代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
class Depth{
int depth;
}
class TreeNode{
int value;
TreeNode right = null;
TreeNode left = null;
TreeNode(int value){
this.value = value;
this.left = this.right = null;
}
}
public class jobdu1350 {
//获得一颗二叉树的深度
public static int getTreeDepth(TreeNode root){
if(root==null)
return 0;
int left = getTreeDepth(root.left);
int right = getTreeDepth(root.right);
return left>right?left+1:right+1;
}
//判断一颗树是否是平衡二叉树
public static boolean isBalance(TreeNode root){
if(root==null)
return true;
int left = getTreeDepth(root.left);
int right = getTreeDepth(root.right);
int diff = left-right;
if(diff>1||diff<-1){
return false;
}
return isBalance(root.left)&&isBalance(root.right);
}
//后序遍历的方式遍历二叉树的每一个结点,在遍历到一个结点之前我们已经遍历了它的左右子树
public static boolean isBalanced(TreeNode root,Depth de){
if(root==null){
de.depth = 0;
return true;
}
Depth left = new Depth();
Depth right = new Depth();
if(isBalanced(root.left,left)&&isBalanced(root.right,right)){
int leftDep = left.depth;
int rightDep = right.depth;
int diff=leftDep-rightDep;
if(diff<=1 && diff>=-1){
de.depth = leftDep>rightDep?leftDep+1:rightDep+1;
System.out.println(de.depth);
return true;
}
}
return false;
}
public static void main(String[] args) throws Exception {
StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
while(cin.nextToken()!=cin.TT_EOF){
int n = (int)cin.nval;
int sign = 1;
TreeNode []array = new TreeNode[n+1];
array[sign++] = new TreeNode(1);
TreeNode root = array[1];
for(int i=1;i<=n;i++){
cin.nextToken();
int left =(int) cin.nval;
cin.nextToken();
int right =(int) cin.nval;
if(left!=-1){
array[sign] =new TreeNode(left);
array[i].left = array[sign];
sign++;
}else{
array[i].left = null;
}
if(right!=-1){
array[sign] = new TreeNode(right);
array[i].right = array[sign];
sign++;
}
}
int depth = getTreeDepth(root);
System.out.println(depth);
Depth de = new Depth();
System.out.println(isBalanced(root,de));
}
}
}