LeetCode 熱題 HOT 100 Java題解——94. 二叉樹的中序遍歷

可達鴨丶發表於2020-10-15

94. 二叉樹的中序遍歷

題目:

給定一個二叉樹,返回它的中序 遍歷。

示例:

輸入: [1,null,2,3]
   1
    \
     2
    /
   3

輸出: [1,3,2]

進階: 遞迴演算法很簡單,你可以通過迭代演算法完成嗎?

迭代中序遍歷

迭代的思想就是構造一個棧,模擬遞迴的操作,遍歷左邊的時候,把一路上的節點存入棧,左邊到頭後,從棧中取出,加入結果集合後再遍歷右邊。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> stack = new LinkedList<>();
        while(root != null || !stack.isEmpty()) {
            while(root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            res.add(root.val);
            root = root.right;
        }
        return res;
    }
}

複雜度分析

  • 時間複雜度: O ( n ) O(n) O(n)

    每個節點被訪問一次。

  • 空間複雜度: O ( n ) O(n) O(n)

    最差情況下遞迴棧大小 O ( n ) O(n) O(n)

Morris中序遍歷

Morris 遍歷演算法整體步驟如下(假設當前遍歷到的節點為 x):

  1. 如果 x x x 無左孩子,先將 x x x 的值加入答案陣列,再訪問 x x x 的右孩子,即 x = x . r i g h t x=x.right x=x.right
  2. 如果 x x x 有左孩子,則找到 x x x 左子樹上最右的節點(即左子樹中序遍歷的最後一個節點, x x x 在中序遍歷中的前驅節點),我們記為 p r e d e c e s s o r predecessor predecessor。根據 p r e d e c e s s o r predecessor predecessor 的右孩子是否為空,進行如下操作。
    1. 如果 p r e d e c e s s o r predecessor predecessor 的右孩子為空,則將其右孩子指向 xx,然後訪問 x x x 的左孩子,即 x = x . l e f t x=x.left x=x.left
    2. 如果 p r e d e c e s s o r predecessor predecessor 的右孩子不為空,則此時其右孩子指向 x x x,說明我們已經遍歷完 x x x 的左子樹,我們將 p r e d e c e s s o r predecessor predecessor 的右孩子置空,將 x x x 的值加入答案陣列,然後訪問 x x x 的右孩子,即 x = x . r i g h t x=x.right x=x.right
  3. 重複上述操作,直至訪問完整棵樹。
public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        while(root != null) {
            if (root.left == null) {
                res.add(root.val);
                root = root.right;
            }
            else {
                TreeNode predecessor = root.left;
                while(predecessor.right != null && predecessor.right != root) predecessor = predecessor.right;
                if (predecessor.right == null) {
                    predecessor.right = root;
                    root = root.left;
                }else {
                    res.add(root.val);
                    predecessor.right = null;
                    root = root.right;
                }

            }
        }
        return res;
    }
}

複雜度分析

  • 時間複雜度: O ( n ) O(n) O(n)

    每個節點被訪問一次。

  • 空間複雜度: O ( 1 ) O(1) O(1)

    利用二叉樹中的空指標,不需要額外空間。

相關文章