天天看點

590. N 叉樹的後序周遊 :「遞歸」&「非遞歸」&「通用非遞歸」

題目描述

這是 LeetCode 上的 ​​590. N 叉樹的後序周遊​​ ,難度為 簡單。

Tag : 「遞歸」、「疊代」、「非遞歸」、「DFS」、「BFS」

給定一個  叉樹的根節點  ,傳回 其節點值的 後序周遊 。

叉樹 在輸入中按層序周遊進行序列化表示,每組子節點由空值 ​​

​null​

​ 分隔(請參見示例)。

示例 1:

590. N 叉樹的後序周遊 :「遞歸」&「非遞歸」&「通用非遞歸」
輸入:root = [1,null,3,2,4,null,5,6]

輸出:[5,6,3,2,4,1]      

示例 2:

590. N 叉樹的後序周遊 :「遞歸」&「非遞歸」&「通用非遞歸」
輸入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]

輸出:[2,6,14,11,7,3,12,8,4,13,9,10,5,1]      

提示:

  • 節點總數在範圍内
  • 叉樹的高度小于或等于

進階:遞歸法很簡單,你可以使用疊代法完成此題嗎?

遞歸

正常做法,不再贅述。

代碼:

class Solution {
    List<Integer> ans = new ArrayList<>();
    public List<Integer> postorder(Node root) {
        dfs(root);
        return ans;
    }
    void dfs(Node root) {
        if (root == null) return;
        for (Node node : root.children) dfs(node);
        ans.add(root.val);
    }
}      
  • 時間複雜度:
  • 空間複雜度:忽略遞歸帶來的額外空間開銷,複雜度為

非遞歸

針對本題,使用「棧」模拟遞歸過程。

疊代過程中記錄 ​

​(cnt = 目前節點周遊過的子節點數量, node = 目前節點)​

​​ 二進制組,每次取出棧頂元素,如果目前節點已經周遊完所有的子節點(目前周遊過的子節點數量為 ),則将目前節點的值加入答案。

否則更新目前元素周遊過的子節點數量,并重新入隊,即将 入隊,以及将下一子節點 進行首次入隊。

代碼:

class Solution {
    public List<Integer> postorder(Node root) {
        List<Integer> ans = new ArrayList<>();
        Deque<Object[]> d = new ArrayDeque<>();
        d.addLast(new Object[]{0, root});
        while (!d.isEmpty()) {
            Object[] poll = d.pollLast();
            Integer cnt = (Integer)poll[0]; Node t = (Node)poll[1];
            if (t == null) continue;
            if (cnt == t.children.size()) ans.add(t.val);
            if (cnt < t.children.size()) {
                d.addLast(new Object[]{cnt + 1, t});
                d.addLast(new Object[]{0, t.children.get(cnt)});
            }
        }
        return ans;
    }
}      
  • 時間複雜度:
  • 空間複雜度:

通用「非遞歸」

另外一種「遞歸」轉「疊代」的做法,是直接模拟系統執行「遞歸」的過程,這是一種更為通用的做法。

由于現代編譯器已經做了很多關于遞歸的優化,現在這種技巧已經無須掌握。

在疊代過程中記錄目前棧幀位置狀态 ​

​loc​

​,在每個狀态流轉節點做相應操作。

代碼:

class Solution {
    public List<Integer> postorder(Node root) {
        List<Integer> ans = new ArrayList<>();
        Deque<Object[]> d = new ArrayDeque<>();
        d.addLast(new Object[]{0, root});
        while (!d.isEmpty()) {
            Object[] poll = d.pollLast();
            Integer loc = (Integer)poll[0]; Node t = (Node)poll[1];
            if (t == null) continue;
            if (loc == 0) {
                d.addLast(new Object[]{1, t});
                int n = t.children.size();
                for (int i = n - 1; i >= 0; i--) d.addLast(new Object[]{0, t.children.get(i)});
            } else if (loc == 1) {
                ans.add(t.val);
            }
        }
        return ans;
    }
}      
  • 時間複雜度:
  • 空間複雜度:

最後

這是我們「刷穿 LeetCode」系列文章的第 ​

​No.590​

​ 篇,系列開始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道題目,部分是有鎖題,我們将先把所有不帶鎖的題目刷完。

繼續閱讀