1. 程式人生 > 遊戲攻略 >《艾爾登法環》女武神招式解析及打法心得 女武神怎麼打

《艾爾登法環》女武神招式解析及打法心得 女武神怎麼打

二叉樹的前序遍歷

題目描述

給你二叉樹的根節點 root ,返回它節點值的 前序 遍歷。

示例 1:

輸入:root = [1,null,2,3]
輸出:[1,2,3]

示例 2:

輸入:root = []
輸出:[]

示例 3:

輸入:root = [1]
輸出:[1]

方法一:遞迴

對於樹的遍歷來說,遞迴的方法永遠是最簡單的。

前序遍歷:根->左子樹->右子樹。

/**
 * 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> preorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        
        preOrder(ans, root);
        return ans;
    }

    private void preOrder(List<Integer> ans, TreeNode root) {
        if (root!=null) {
            ans.add(root.val);
            preOrder(ans, root.left);
            preOrder(ans, root.right);
        }
    }
}

方法二:迭代

​ 我們也可以用迭代的方式實現方法一的遞迴函式,兩種方式是等價的,區別在於遞迴的時候隱式地維護了一個棧,而我們在迭代的時候需要顯式地將這個棧模擬出來,其餘的實現與細節都相同,具體可以參考下面的程式碼。

思路:針對二叉樹先序遍歷 根->左子樹->右子樹 的順序

  • 對於每一個結點,我們一直遍歷到它的最左邊
  • 然後返回上一個結點
  • 再遍歷它的右邊。
/**
 * 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> preorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        while (root!=null || !stack.isEmpty()) {
            while (root!=null) {
                ans.add(root.val);
                stack.add(root);
                root = root.left;
            }
            root = stack.pop();
            root = root.right;
        }
        return ans;
    }
}

方法三:Morris 遍歷

Morris 遍歷的核心思想是利用樹的大量空閒指標,實現空間開銷的極限縮減。其前序遍歷規則總結如下:

  1. 新建臨時節點,令該節點為 root
  2. 如果當前節點的左子節點為空,將當前節點加入答案,並遍歷當前節點的右子節點;
  3. 如果當前節點的左子節點不為空,在當前節點的左子樹中找到當前節點在中序遍歷下的前驅節點:
    • 如果前驅節點的右子節點為空,將前驅節點的右子節點設定為當前節點。然後將當前節點加入答案,並將前驅節點的右子節點更新為當前節點。當前節點更新為當前節點的左子節點。
    • 如果前驅節點的右子節點為當前節點,將它的右子節點重新設為空。當前節點更新為當前節點的右子節點。
  4. 重複步驟 2 和步驟 3,直到遍歷結束。
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        if (root == null) {
            return res;
        }

        TreeNode p1 = root, p2 = null;

        while (p1 != null) {
            p2 = p1.left;
            if (p2 != null) {
                while (p2.right != null && p2.right != p1) {
                    p2 = p2.right;
                }
                if (p2.right == null) {
                    res.add(p1.val);
                    p2.right = p1;
                    p1 = p1.left;
                    continue;
                } else {
                    p2.right = null;
                }
            } else {
                res.add(p1.val);
            }
            p1 = p1.right;
        }
        return res;
    }
}