1. 程式人生 > 其它 >145. 二叉樹的後序遍歷(java實現)--LeetCode

145. 二叉樹的後序遍歷(java實現)--LeetCode

技術標籤:演算法題樹算髮題演算法leetcodejava

文章目錄

題目:

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

示例:

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

輸出: [3,2,1]

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

解法1:遞迴

    public List<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer>
result = new ArrayList<>(); recursive(result,root); return result; } private void recursive(ArrayList<Integer> result, TreeNode root) { if (root==null)return; recursive(result,root.left); recursive(result,root.right); result.add(root.
val); }

時間複雜度:On

空間複雜度:On
在這裡插入圖片描述

解法2:stack

/**
 * 思路:
 * 先走到極左
 * 之後判斷是否有右側節點
 * 沒有,加入結果集,記錄當前節點為右子樹,用來判斷是否走過右側,root賦值為null
 * 有,root賦值為root.right
 */
    public List<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<>();
        ArrayDeque<
TreeNode>
stack = new ArrayDeque<>(); //保證右側不會走第二遍 TreeNode right_record=null; while (!stack.isEmpty()||root!=null){ while (root!=null){ stack.push(root); root=root.left; } root=stack.pop(); if (root.right==null||root.right==right_record) { result.add(root.val); //記錄右子樹,用來標記是否走過右側 right_record=root; root=null; }else { stack.push(root); root=root.right; } } return result; }

時間複雜度:On

空間複雜度:On
在這裡插入圖片描述

解法3:Morris

/**
 * 新建臨時節點,令該節點為 root;
 *
 * 如果當前節點的左子節點為空,則遍歷當前節點的右子節點;
 *
 * 如果當前節點的左子節點不為空,在當前節點的左子樹中找到當前節點在中序遍歷下的前驅節點;
 *
 * 如果前驅節點的右子節點為空,將前驅節點的右子節點設定為當前節點,當前節點更新為當前節點的左子節點。
 *
 * 如果前驅節點的右子節點為當前節點,將它的右子節點重新設為空。倒序輸出從當前節點的左子節點到該前驅節點這條路徑上的所有節點。當前節點更新為當前節點的右子節點。
 *
 * 重複步驟 2 和步驟 3,直到遍歷結束。
 */
    public List<Integer> postorderTraversal(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) {
                    p2.right = p1;
                    p1 = p1.left;
                    continue;
                } else {
                    p2.right = null;
                    addPath(res, p1.left);
                }
            }
            p1 = p1.right;
        }
        addPath(res, root);
        return res;
    }

    public void addPath(List<Integer> res, TreeNode node) {
        int count = 0;
        while (node != null) {
            ++count;
            res.add(node.val);
            node = node.right;
        }
        int left = res.size() - count, right = res.size() - 1;
        while (left < right) {
            int temp = res.get(left);
            res.set(left, res.get(right));
            res.set(right, temp);
            left++;
            right--;
        }
    }

時間複雜度:On

空間複雜度:On
在這裡插入圖片描述

解法4:顏色遍歷

/**
 * 思路:
 * 顏色標記,0是沒走過,1是走過
 * 在棧中存放paris 0/1,node
 * 如果當前節點是沒走過,按照根右左的順序加入棧中
 */
    public List<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<>();
        if (root==null)return result;
        ArrayDeque<Pair<Integer,TreeNode>> stack = new ArrayDeque<>();
        stack.push(new Pair<>(0,root));
        while (!stack.isEmpty()){
            Pair<Integer, TreeNode> pop = stack.pop();
            if (pop.getKey()==0) {
                stack.push(new Pair<>(1, pop.getValue()));
                if (pop.getValue().right!=null) stack.push(new Pair<>(0, pop.getValue().right));
                if (pop.getValue().left!=null) stack.push(new Pair<>(0, pop.getValue().left));
            }else {
                result.add(pop.getValue().val);
            }
        }
        return result;
    }

時間複雜度:On

空間複雜度:On
在這裡插入圖片描述