題目:輸入一棵二叉樹的根節點,求該數的深度。從根節點到葉結點依次進過的結點(含根,葉結點)造成樹的一條路徑,最長路徑的長度爲樹的深度。node
例如,以下圖的二叉樹的深度爲4,由於它從根節點到葉結點的最長的路徑包含4個結點(從根結點1開始,通過2和結點5,最終到達葉結點7)面試
咱們能夠從另外一種角度來理解樹的深度。若是一棵樹只有一個結點,它的 深度爲1,若是根節點只有左子樹而沒有右子樹,那麼樹的深度應該是其左子樹的深度+1.一樣若是根節點只有右子樹而沒有左子樹,那麼樹的深度應該是其右子 樹+1.若是既有左子樹又有右子樹,那概述的深度就是左、右子樹的深度的較大值加1.。算法
利用這個思路,咱們能夠用遞歸來實現代碼:編程
package cglib;函數
class BinaryTreeNode{
int data;
BinaryTreeNode leftNode;
BinaryTreeNode rightNode;
}性能
public class jiekou {遞歸
//普通二叉樹求深度
public int treeDepth(BinaryTreeNode root){
if(root == null)
return 0;
System.out.println("treeDepth遞歸");
int nLeft = treeDepth(root.leftNode);
System.out.println("nLeft="+nLeft);
System.out.println("nRight前treeDepth遞歸");
int nRight = treeDepth(root.rightNode);
System.out.println("nRight後");
System.out.println("nRight="+nRight);
return (nLeft > nRight)?(nLeft+1):(nRight+1);
}
public static void main(String[] args){
BinaryTreeNode root=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
BinaryTreeNode node5=new BinaryTreeNode();
BinaryTreeNode node6=new BinaryTreeNode();
root.leftNode=node1;
root.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
node2.rightNode=node5;
node4.leftNode=node6;
root.data=1;
node1.data=2;
node2.data=3;
node3.data=4;
node4.data=5;
node5.data=6;
node6.data=7;
jiekou test = new jiekou();
System.out.println(test.treeDepth(root));
}
}class
輸出:4test
若是公司對編程能力有較高的要求,面試官可能會追加一個與前面的問題相關但難度較大的問題,好比,應聘者作完上面的問題後,面試官追問:效率
題目二:輸入一棵二叉樹的根節點,判斷該樹是否是平衡的二叉樹。若是某二叉樹中任意結點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。
須要重複遍歷結點屢次的解法,簡單但不足以打動面試官
有了求二叉樹的深度的經驗以後再解決這個問題,咱們很容易就能想到一個思路:在遍歷樹的每一個結點的時候,調用函數TreeDepth獲得它的左右子樹的深度。若是每一個結點的左右子樹的深度相差不超過1,按照定義它就是一棵平衡的二叉樹。這種思路實現的代碼以下:
package cglib;
class BinaryTreeNode{
int data;
BinaryTreeNode leftNode;
BinaryTreeNode rightNode;
}
public class jiekou {
//普通二叉樹求深度
public int treeDepth(BinaryTreeNode root){
if(root == null)
return 0;
System.out.println("treeDepth遞歸");
int nLeft = treeDepth(root.leftNode);
System.out.println("nLeft="+nLeft);
System.out.println("nRight前treeDepth遞歸");
int nRight = treeDepth(root.rightNode);
System.out.println("nRight後");
System.out.println("nRight="+nRight);
return (nLeft > nRight)?(nLeft+1):(nRight+1);
}
public boolean isBalanced(BinaryTreeNode root){
if(root ==null)
return true;
int left = treeDepth(root.leftNode);
int right = treeDepth(root.rightNode);
int diff = left - right;
if(diff > 1 || diff <-1)
return false;
return isBalanced(root.leftNode) && isBalanced(root.rightNode);
}
public static void main(String[] args){
BinaryTreeNode root=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
BinaryTreeNode node5=new BinaryTreeNode();
BinaryTreeNode node6=new BinaryTreeNode();
root.leftNode=node1;
root.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
node2.rightNode=node5;
node4.leftNode=node6;
root.data=1;
node1.data=2;
node2.data=3;
node3.data=4;
node4.data=5;
node5.data=6;
node6.data=7;
jiekou test = new jiekou();
System.out.println(test.treeDepth(root));
System.out.println(test.isBalanced(root));
}
}
輸出:
treeDepth遞歸
treeDepth遞歸
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
nLeft=1
nRight前treeDepth遞歸
treeDepth遞歸
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
nLeft=1
nRight前treeDepth遞歸
nRight後
nRight=0
nRight後
nRight=2
nLeft=3
nRight前treeDepth遞歸
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
nRight後
nRight=1
nRight後
nRight=2
4
treeDepth遞歸
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
nLeft=1
nRight前treeDepth遞歸
treeDepth遞歸
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
nLeft=1
nRight前treeDepth遞歸
nRight後
nRight=0
nRight後
nRight=2
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
nRight後
nRight=1
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
treeDepth遞歸
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
nLeft=1
nRight前treeDepth遞歸
nRight後
nRight=0
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
treeDepth遞歸
nLeft=0
nRight前treeDepth遞歸
nRight後
nRight=0
true
上面的代碼當然簡潔,但咱們也注意到因爲一個結點會被重複遍歷屢次,這種 思路的時間效率不高。例如在函數isBalanced中輸入上圖中的二叉樹,咱們將首先判斷根節點是否是平衡的。此時咱們網函數TreeDepth輸入左 子樹的根節點時須要遍歷結點4,5,7.接下來判斷以結點2爲根節點的子樹是否是平衡樹的時候,仍然會遍歷結點4,5,7.毫無疑問,重複遍歷同一個結點 會影響性能。接下來咱們尋找不須要重複遍歷的算法。
package cglib;
class BinaryTreeNode{
int data;
BinaryTreeNode leftNode;
BinaryTreeNode rightNode;
}
public class jiekou {
//普通二叉樹求深度
public int treeDepth(BinaryTreeNode root){
if(root == null)
return 0;
System.out.println("treeDepth遞歸");
int nLeft = treeDepth(root.leftNode);
System.out.println("nLeft="+nLeft);
System.out.println("nRight前treeDepth遞歸");
int nRight = treeDepth(root.rightNode);
System.out.println("nRight後");
System.out.println("nRight="+nRight);
return (nLeft > nRight)?(nLeft+1):(nRight+1);
}
public boolean isBalanced(BinaryTreeNode root){
if(root ==null)
return true;
int left = treeDepth(root.leftNode);
int right = treeDepth(root.rightNode);
int diff = left - right;
if(diff > 1 || diff <-1)
return false;
return isBalanced(root.leftNode) && isBalanced(root.rightNode);
}
//高效率的判斷是不是一棵平衡二叉樹
public boolean isBalanced2(BinaryTreeNode root){
int depth = 0;
return isBalanced2(root,depth);
}
public boolean isBalanced2(BinaryTreeNode root,int depth){
if(root == null){
depth = 0;
return true;
}
int left = 0,right = 0;
if(isBalanced2(root.leftNode,left) && isBalanced2(root.rightNode,right)){
int diff = left-right;
if(diff <= 1 && diff >= -1){
depth = 1+(left > right?left : right);
return true;
}
}
return false;
}
public static void main(String[] args){
BinaryTreeNode root=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
BinaryTreeNode node5=new BinaryTreeNode();
BinaryTreeNode node6=new BinaryTreeNode();
root.leftNode=node1;
root.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
node2.rightNode=node5;
node4.leftNode=node6;
root.data=1;
node1.data=2;
node2.data=3;
node3.data=4;
node4.data=5;
node5.data=6;
node6.data=7;
jiekou test = new jiekou();
System.out.println(test.treeDepth(root));
System.out.println(test.isBalanced(root));
System.out.println(test.isBalanced2(root));
}
}
在上面的代碼中,咱們用後序遍歷的方式遍歷整棵二叉樹。在遍歷某結點的左右子樹結點以後,咱們就能夠根據它的左右子樹的深度判斷它時不時平衡的,並獲得當前結點的深度。當最後遍歷到樹的根節點的時候,也就判斷了整棵二叉樹是否是平衡二叉樹。