題目:
輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度爲樹的深度。
題中定義了二叉樹的深度爲:最長的一條路徑長度即爲樹的深度。
可以分爲幾種情況:
- 如果樹只有左子樹,沒有右子樹,則樹的深度應該爲左子樹深度+1。
- 如果樹只有右子樹,沒有左子樹,則樹的深度爲右子樹深度+1。
- 如果樹既有左子樹又有右子樹,則整個樹的深度爲max(左子樹深度,右子樹深度)+1。
1. 遞歸方法
根據以上思路可以寫出遞歸版本的求解二叉樹的深度:
public class Solution {
public int TreeDepth(TreeNode root) {
if(root == null){
return 0;
}
if(root.left == null && root.right != null){
return TreeDepth(root.right)+1;
}else if(root.left != null && root.right == null){
return TreeDepth(root.left)+1;
}else{
return Math.max(TreeDepth(root.left),TreeDepth(root.right))+1;
}
}
}
2. 非遞歸版本
上面遞歸版本是計算每一條路徑的節點數,和深度搜索有點像。如果不是一條路徑執行到底,而是一層一層的往外遍歷呢?
一層一層遍歷,想到了什麼?
廣度優先搜索,聯繫到二叉樹,也就是層序遍歷,層序遍歷是借用輔助空間隊列。每次拉出一個節點之後,將該節點的左右子節點添加到隊列中。只是本題中需要每次記住層次。
怎麼知道這一層遍歷完了呢?
利用兩個數據,num、nextNum,前者表示當前層遍歷到第幾個元素,後者便是本層元素個數(或者說下一層元素個數)。
具體的流程如下:
import java.util.*;
public class Solution {
public int TreeDepth(TreeNode root) {
if(root == null){
return 0;
}
Queue<TreeNode> nodes = new LinkedList<TreeNode>();
nodes.add(root);
int level = 0;
int num = 0;
int nextNum = 1;
while(nodes.size() != 0){
TreeNode top = nodes.poll();
num++;
if(top.left != null){
nodes.add(top.left);
}
if(top.right != null){
nodes.add(top.right);
}
// 如果這個if條件成立,則說明本層所有的節點已經全部彈出,則將nextNum更新爲下一層節點個數
if(num == nextNum){
nextNum = nodes.size();
num = 0;
level++;
}
}
return level;
}
}
總結
求解二叉樹的深度,遞歸方法比較簡單,循環方法稍稍複雜,但是只需要掌握了層次遍歷的核心(藉助隊列),問題自然簡單了很多。
一定要熟悉各種不同遍歷方式的輔助工具。