標籤:
題目:輸入一棵二叉樹的根節點,求該數的深度。從根節點到葉結點依次進過的結點(含根,葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。
例如,如的二叉樹的深度為4,因為它從根節點到葉結點的最長的路徑包含4個結點(從根結點1開始,經過2和結點5,最終到達葉結點7)
我們可以從另一種角度來理解樹的深度。如果一棵樹只有一個結點,它的深度為1,如果根節點只有左子樹而沒有右子樹,那麼樹的深度應該是其左子樹的深度+1.同樣如果根節點只有右子樹而沒有左子樹,那麼樹的深度應該是其右子樹+1.如果既有左子樹又有右子樹,那概述的深度就是左、右子樹的深度的較大值加1.。
利用這個思路,我們可以用遞迴來實現代碼:
//普通二叉樹求深度public int treeDepth(BinaryTreeNode root){if(root == null)return 0;int nLeft = treeDepth(root.leftNode);int nRight = treeDepth(root.rightNode);return (nLeft > nRight)?(nLeft+1):(nRight+1);} 如果公司對編程能力有較高的要求,面試官可能會追加一個與前面的問題相關但難度較大的問題,比如,應聘者做完上面的問題後,面試官追問:
題目二:輸入一棵二叉樹的根節點,判斷該樹是不是平衡的二叉樹。如果某二叉樹中任意結點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。
需要重複遍曆結點多次的解法,簡單但不足以打動面試官
有了求二叉樹的深度的經驗之後再解決這個問題,我們很容易就能想到一個思路:在遍曆樹的每個結點的時候,調用函數TreeDepth得到它的左右子樹的深度。如果每個結點的左右子樹的深度相差不超過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);} 上面的代碼固然簡潔,但我們也注意到由於一個結點會被重複遍曆多次,這種思路的時間效率不高。例如在函數isBalanced中輸入中的二叉樹,我們將首先判斷根節點是不是平衡的。此時我們網函數TreeDepth輸入左子樹的根節點時需要遍曆結點4,5,7.接下來判斷以結點2為根節點的子樹是不是平衡樹的時候,仍然會遍曆結點4,5,7.毫無疑問,重複遍曆同一個結點會影響效能。接下來我們尋找不需要重複遍曆的演算法。
每個結點只遍曆一次的解法,正是面試官喜歡的演算法
如果我們用後序遍曆的方式遍曆二叉樹的每個結點,在遍曆一個結點之前我們就已經遍曆了它的左右子樹。只要在遍曆每個結點的時候我們記錄它的深度(某一節點的深度等於它到葉結點的路徑的長度),我們就可以一邊遍曆一邊判斷每個結點是不是平衡二叉樹。下面是這種思路的實現代碼:
//高效率的判斷是否是一棵平衡二叉樹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;}
在上面的代碼中,我們用後序遍曆的方式遍曆整棵二叉樹。在遍曆某結點的左右子樹結點之後,我們就可以根據它的左右子樹的深度判斷它時不時平衡的,並得到當前結點的深度。當最後遍曆到樹的根節點的時候,也就判斷了整棵二叉樹是不是平衡二叉樹。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
劍指Offer面試題39(Java版):二叉樹的深度