題目一:輸入一棵二叉樹的根結點,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。例如下圖中的二叉樹的深度為4,因為它從根結點到葉結點最長的路徑包含4個結點(從根結點1開始,經過結點2和結點5,最終到達葉結點7)。二叉樹的結點定義如下,這裡使用c#語言描述:
public①如果一棵樹只有乙個結點,它的深度為1。class
binarytreenode
public binarytreenode leftchild
public binarytreenode rightchild
public binarytreenode(int
data)
public binarytreenode(int
data, binarytreenode left, binarytreenode right)
}
②如果根結點只有左子樹而沒有右子樹,那麼樹的深度應該是其左子樹的深度加1;同樣如果根結點只有右子樹而沒有左子樹,那麼樹的深度應該是其右子樹的深度加1。
③如果既有右子樹又有左子樹,那該樹的深度就是其左、右子樹深度的較大值再加1。
比如在上圖的二叉樹中,根結點為1的樹有左右兩個子樹,其左右子樹的根結點分別為結點2和3。根結點為2的左子樹的深度為3,而根結點為3的右子樹的深度為2,因此根結點為1的樹的深度就是4。
public(1)測試用例static
intgettreedepth(binarytreenode root)
int left =gettreedepth(root.leftchild);
int right =gettreedepth(root.rightchild);
return left >= right ? left + 1 : right + 1
; }
[testclass](2)測試結果public
class
treedepthtest
root.leftchild =lchild;
root.rightchild =rchild;
}private
void
clearuptreenode(binarytreenode root)
}//1
/// \
//2 3
///\ \
//4 5 6
/////7
[testmethod]
public
void
getdepthtest1()
//1///
//2///
//3///
//4///
//5[testmethod]
public
void
getdepthtest2()
//1//\
//2//\
//3//\
//4//\
//5[testmethod]
public
void
getdepthtest3()
//樹中只有1個結點
[testmethod]
public
void
getdepthtest4()
//樹中沒有結點
[testmethod]
public
void
getdepthtest5()
}
①測試通過情況
②**覆蓋率
題目二:輸入一棵二叉樹的根結點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意結點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。例如,下圖中的二叉樹就是一棵平衡二叉樹。(1)需要重複遍歷節點多次的解法有了求二叉樹的深度的經驗之後再解決這個問題,我們很容易就能想到乙個思路:在遍歷樹的每個結點的時候,呼叫函式treedepth得到它的左右子樹的深度。如果每個結點的左右子樹的深度相差都不超過1,按照定義它就是一棵平衡的二叉樹。
public上面的**固然簡潔,但我們也要注意到由於乙個結點會被重複遍歷多次,這種思路的時間效率不高。例如在isbalancedbinarytree方法中輸入上圖中的二叉樹,我們將首先判斷根結點(結點1)是不是平衡的。此時我們往函式treedepth輸入左子樹的根結點(結點2)時,需要遍歷結點4、5、7。接下來判斷以結點2為根結點的子樹是不是平衡樹的時候,仍然會遍歷結點4、5、7。毫無疑問,重複遍歷同乙個結點會影響效能。static
bool
isbalancedbinarytree(binarytreenode root)
int left =gettreedepth(root.leftchild);
int right =gettreedepth(root.rightchild);
int diff = left -right;
if (diff > 1 || diff < -1
)
return isbalancedbinarytree(root.leftchild) &&isbalancedbinarytree(root.rightchild);
}
(2)每個節點只需遍歷一次的解法
換個角度來思考,如果我們用後序遍歷的方式遍歷二叉樹的每乙個結點,在遍歷到乙個結點之前我們就已經遍歷了它的左右子樹。只要在遍歷每個結點的時候記錄它的深度(某一結點的深度等於它到葉節點的路徑的長度),我們就可以一邊遍歷一邊判斷每個結點是不是平衡的。
public在上面的**中,我們用後序遍歷的方式遍歷整棵二叉樹。在遍歷某結點的左右子結點之後,我們可以根據它的左右子結點的深度判斷它是不是平衡的,並得到當前結點的深度。當最後遍歷到樹的根結點的時候,也就判斷了整棵二叉樹是不是平衡二叉樹。static
bool
isbalancedbinarytree(binarytreenode root)
private
static
bool isbalancedbinarytreecore(binarytreenode root, ref
intdepth)
int left = 0
;
int right = 0
;
if (isbalancedbinarytreecore(root.leftchild, ref left) && isbalancedbinarytreecore(root.rightchild, ref
right))
}return
false
; }
此方法的單元測試和第一種方法的一致,這裡就不再貼出。需要注意的就是在針對二叉樹的測試用例中,需要考慮兩種:功能測試(平衡的二叉樹,不是平衡的二叉樹,二叉樹中所有結點都沒有左/右子樹)。特殊輸入測試(二叉樹中只有乙個結點,二叉樹的頭結點為null指標)。
出處:
《劍指Offer》面試題 平衡二叉樹
題目 輸入乙個二叉樹的根節點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意節點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。思路 用後序遍歷實現 先遍歷節點的左右子樹,左右子樹都平衡才來判斷該節點是否平衡,如果左右子樹中有不平衡的,則直接返回false,避免了從上往下逐個節點地計算深度帶來...
劍指Offer 面試題 樹和二叉樹
題目描述 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列和中序遍歷序列,則重建二叉樹並返回。基礎知識 在二叉樹的前序遍歷序列中,第乙個數字總是樹的根節點的值。在中序遍歷序列中,根節點的值在序列的中間,左子樹的節點的...
劍指offer面試題33二叉搜尋樹的後序遍歷序列
輸入乙個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則輸出yes,否則輸出no。假設輸入的陣列的任意兩個數字都互不相同。設計思想 序列的最後乙個元素一定是整棵樹的根節點,從序列開頭找第乙個大於根節點值的元素p val,該元素後邊直到末尾前乙個元素的元素值應該都大於p val 若p到...