【力扣】104. 二叉樹的最大深度-及二叉樹的遍歷方式
阿新 • • 發佈:2020-07-28
給定一個二叉樹,找出其最大深度。
二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。
說明:葉子節點是指沒有子節點的節點。
示例:
給定二叉樹 [3,9,20,null,null,15,7],3
/ \
9 20
/ \
15 7
返回它的最大深度3 。來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int x) {
val = x;
}
}
解法1:遞迴
public int maxDepth(TreeNode root) {
if (root == null){
return 0;
}
return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
}
藉此學習下二叉樹的遍歷方法:
二叉樹有兩種遍歷方式,第一種是深度優先遍歷演算法,深度優先又分為前序遍歷、中序遍歷、後序遍歷,第二種是廣度優先遍歷演算法,也就是層次遍歷
前序遍歷:1 2 4 5 7 8 3 6
中序遍歷:4 2 7 5 8 1 3 6
後序遍歷:4 7 8 5 2 6 3 1
層次遍歷:1 2 3 4 5 6 7 8
深度優先:
深度優先中的前序遍歷:根結點 ---> 左子樹 ---> 右子樹
/** * 二叉樹的深度優先遍歷演算法中的前序遍歷 (遞迴) */ public List preOrder(TreeNode root) { if (root == null){ return null; } List<Integer> list = newArrayList<>(); search(list,root); return list; } public void search(List<Integer> list,TreeNode root){ if (root != null){ list.add(root.val); search(list,root.left); search(list,root.right); } }
/** * 二叉樹的深度優先遍歷演算法中的前序遍歷 使用棧 * */ public List preOrderUseStack(TreeNode root) { if (root == null){ return null; } List<Integer> list = new ArrayList<>(); Stack<TreeNode> stack = new Stack(); //也可以用棧實現 棧的特性是先進後出 stack.push(root); //若棧不空 while(!stack.isEmpty()){ //取出響應的節點 TreeNode node=stack.pop(); list.add(node.val); //考慮到先進後出的特性,所以先放右子節點 if(node.right!=null){ stack.push(node.right); } if(node.left!=null){ stack.push(node.left); } } return list; }
深度優先中的中序遍歷:左子樹 --->根結點 ---> 右子樹
/** * 中序遍歷 */ public List centerOrderUseStack(TreeNode root) { if (root == null){ return null; } List<Integer> list = new ArrayList<>(); Stack<TreeNode> stack = new Stack(); //也可以用棧實現 棧的特性是先進後出 TreeNode currentNode = root; //若棧不空 while(currentNode != null || !stack.isEmpty()){ while(currentNode != null){ stack.push(currentNode); currentNode = currentNode.left; } //取出響應的節點 currentNode=stack.pop(); list.add(currentNode.val); currentNode = currentNode.right; } return list; }
深度優先中的後序遍歷:左子樹---> 右子樹--->根結點
/** * 後序遍歷,後序遍歷的特殊點在於我們要最後獲取到根節點 還是很複雜的!!!!!! */ public List afterWordUseStack(TreeNode root) { if (root == null){ return null; } List<Integer> list = new ArrayList<>(); Stack<TreeNode> stack = new Stack(); //也可以用棧實現 棧的特性是先進後出 TreeNode currentNode = root; TreeNode rightNode = null; //若棧不空 while(currentNode != null || !stack.isEmpty()){ //一直迴圈到最左端的葉子結點(currentNode是null) while(currentNode != null){ stack.push(currentNode); currentNode = currentNode.left; } //取出相應的節點 currentNode=stack.pop(); //若右節點是空,或者 當前節點的右節點為右節點 這樣迴圈完成可以得到currentNode 父節點 while(currentNode.right == null || currentNode.right == rightNode){ list.add(currentNode.val); rightNode = currentNode; // 設定右節點為當前節點 if (stack.isEmpty()){ return list; } currentNode=stack.pop(); } stack.push(currentNode); //還有右結點沒有遍歷 currentNode = currentNode.right; } return list; }
廣度優先:
/** * 廣度優先遍歷 又稱層級遍歷 需要藉助資料結構 : 佇列 */ public List spanUseStack(TreeNode root) { if (root == null){ return null; } //佇列的特性為:先進先出 ArrayDeque<TreeNode> deque = new ArrayDeque<TreeNode>(); List<Integer> list = new ArrayList<>(); deque.add(root); while(!deque.isEmpty()){ TreeNode current = deque.remove(); list.add(current.val); if (current.left != null){ deque.add(current.left); } if (current.right != null){ deque.add(current.right); } } return list; }