[LeetCode] #94 二叉樹的中序周遊
給定一個二叉樹的根節點
root
,傳回它的 中序 周遊。 
輸入:root = [1,null,2,3]
輸出:[1,3,2]
二叉樹周遊,最經典的方法肯定是遞歸
遞歸有三部曲
(1)找整個遞歸的終止條件:遞歸應該在什麼時候結束? 節點為null
(2)找傳回值:應該給上一級傳回什麼資訊?本節點的中序周遊List
(3)本級遞歸應該做什麼:在這一級遞歸中,應該完成什麼任務?本節點List追加左子樹List,追加自己的val,追加右子樹List
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) return res;
res.addAll(inorderTraversal(root.left));
res.add(root.val);
res.addAll(inorderTraversal(root.right));
return res;
}
}
遞歸也可以用疊代的方式實作,兩種方式是等價的,差別在于遞歸的時候隐式地維護了一個棧,而我們在疊代的時候需要顯式地将這個棧模拟出來,其他都相同。
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Deque<TreeNode> stk = new LinkedList<TreeNode>();
while (root != null || !stk.isEmpty()) {
while (root != null) {
stk.push(root);
root = root.left;
}
root = stk.pop();
res.add(root.val);
root = root.right;
}
return res;
}
}
Morris中序周遊,是另一種周遊二叉樹的方法,它能将非遞歸的中序周遊空間複雜度降為 O(1)。
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
TreeNode predecessor = null;
while (root != null) {
if (root.left != null) {
// predecessor 節點就是目前 root 節點向左走一步,然後一直向右走至無法走為止
predecessor = root.left;
while (predecessor.right != null && predecessor.right != root) {
predecessor = predecessor.right;
}
// 讓 predecessor 的右指針指向 root,繼續周遊左子樹
if (predecessor.right == null) {
predecessor.right = root;
root = root.left;
}
// 說明左子樹已經通路完了,我們需要斷開連結
else {
res.add(root.val);
predecessor.right = null;
root = root.right;
}
}
// 如果沒有左孩子,則直接通路右孩子
else {
res.add(root.val);
root = root.right;
}
}
return res;
}
}
知識點: