劍指Offer-40-二叉樹的深度
題目
輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。
解析
預備知識
樹的深度為根節點到葉子節點中所有的路徑長度最長的值。如圖:
圖中根節點到葉子節點最長的路徑為:1->3->5->6
,所以深度為4.
思路一
我們很容易想到一個樹深度為左子樹和右子樹深度的最大值 + 1。所以問題規模轉變為求左子樹和右子樹的深度,問題形式不變,規模變小,典型的遞迴問題。所以很容易寫出如下精簡的程式碼:
public static int TreeDepth4(TreeNode root) {
if(root == null) {
return 0;
}
int left = TreeDepth4(root.left);
int right = TreeDepth4(root.right);
return Math.max(left, right) + 1;
}
思路二
我們都知道遞迴在問題規模很大的時候容易出現棧溢位,所以我們嘗試換種思路來避免遞迴。
在樹的遍歷中,實現簡單而不是遞迴的寫法就屬層序遍歷了。
層序遍歷:顧名思義,就是從根節點一層一層的遍歷整棵樹。
我們可以按層來處理,每遍歷一層,深度加一,直到遍歷完整棵樹,即可得到層數(即深度)。層序遍歷也就是BFS非常適合用先進先出的佇列來充當容器,深度初始為0,根節點先入隊,然後處理第一層,深度加1,並把第二層的節點加入;之後繼續處理第二層,深度加1,獲取當前佇列的大小,此時佇列的大小即為當前層節點總數size,依次從佇列中取出大小為size的節點,期間並把這些節點的孩子節點加入(即下一層的);重複以上步驟,直到佇列為空,表明遍歷到最底層。
public static int TreeDepth(TreeNode root) {
if(root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int depth = 0;
while(!queue.isEmpty()) {
int currentLayerSize = queue.size();
depth++;
for(int i = 0; i < currentLayerSize; i++) {
TreeNode node = queue.poll();
if(node.left != null) {
queue.offer(node.left);
}
if(node.right != null) {
queue.offer(node.right);
}
}
}
return depth;
}
思路三
思路三跟思路二一樣,只不過按層處理的策略不同。
思路二是通過每次把當前層的節點彈出來確保最外層每次訪問都是樹的每一層。
而思路三是借用2個指標last,nLast。其中last指向當前層的最後一個節點,nLast指向下一層的最後一個節點。
1. 初始last指向根節點,root進棧。
2. 開始迴圈體,判斷棧是否為空,不為空,則彈出節點node,繼續步驟3;否則步驟5
3. 判斷node的左右孩子是否不為空,若不為空,則入隊,並更新nLast指向孩子。
4. 判斷node是否等於last,若是,則表明下一次該訪問下一層了,所以深度加1,並把last更新為nLast
5. 結束迴圈,返回深度
public static int TreeDepth3(TreeNode root) {
if(root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int depth = 0;
TreeNode last = root, nLast = null;
while(!queue.isEmpty()) {
TreeNode node = queue.poll();
if(node.left != null) {
queue.offer(node.left);
nLast = node.left;
}
if(node.right != null) {
queue.offer(node.right);
nLast = node.right;
}
if(node == last) {
depth++;
last = nLast;
}
}
return depth;
}
總結
有序陣列的查詢首選二分查詢。
相關文章
- 劍指offer——二叉樹的深度C++二叉樹C++
- 劍指offer | 55 - I. 二叉樹的深度二叉樹
- 劍指offer——重建二叉樹二叉樹
- 劍指offer(四)重建二叉樹二叉樹
- 【劍指offer】27. 二叉樹的映象二叉樹
- 劍指offer——二叉樹的映象C++二叉樹C++
- 劍指 Offer 07. 重建二叉樹二叉樹
- [劍指offer] 把二叉樹列印成多行二叉樹
- 【劍指offer】5.二叉樹的映象和列印二叉樹
- 力扣 - 劍指 Offer 27. 二叉樹的映象力扣二叉樹
- # 劍指 Offer 68 - II. 二叉樹的最近公共祖先二叉樹
- [劍指offer] 二叉搜尋樹的後序遍歷序列
- leetcode 102 劍指Offer 32 二叉樹的層次遍歷LeetCode二叉樹
- 二叉樹的深度二叉樹
- 劍指offer--把二叉樹列印成多行(C++)二叉樹C++
- 《劍指offer》之在完全二叉樹中新增子節點二叉樹
- 劍指offer——從上往下列印二叉樹C++二叉樹C++
- LeetCode 劍指offer——從上到下列印二叉樹 II、從上到下列印二叉樹 IIILeetCode二叉樹
- 二叉樹深度二叉樹
- 二叉樹---深度二叉樹
- 劍指 Offer 32 - III. 從上到下列印二叉樹 III二叉樹
- 劍指 Offer 33. 二叉搜尋樹的後序遍歷序列
- 劍指 Offer 34. 二叉樹中和為某一值的路徑二叉樹
- 二叉樹的最大深度和最小深度二叉樹
- 二叉樹的最大/最小深度二叉樹
- 二叉樹的最大深度20201231二叉樹
- 二叉樹的子結構、深度以及重建二叉樹二叉樹
- 劍指 Offer 54. 二叉搜尋樹的第k大節點 mark
- (python版)《劍指Offer》JZ57:二叉樹的下一個結點Python二叉樹
- 力扣 - 劍指 Offer 54. 二叉搜尋樹的第k大節點力扣
- 劍指offer(java實現)第4題“重建二叉樹”-牛客網Java二叉樹
- 【劍指offer】【4】根據前序和中序結果,重建二叉樹二叉樹
- 劍指 Offer 32 - I. 從上到下列印二叉樹(java解題)二叉樹Java
- 111. 二叉樹的最小深度(***)二叉樹
- 111. 二叉樹的最小深度二叉樹
- 104. 二叉樹的最大深度二叉樹
- JZ-038-二叉樹的深度二叉樹
- 二叉樹的最小深度問題二叉樹