1. 程式人生 > >102#二叉樹的層序遍歷

102#二叉樹的層序遍歷

剛才 怎麽 eve 子節點 class 算法 一個隊列 所有 創建

題目描述

給定一個二叉樹,返回其按層次遍歷的節點值。 (即逐層地,從左到右訪問所有節點)。

例如:
給定二叉樹: [3,9,20,null,null,15,7],

    3
   /   9  20
    /     15   7

返回其層次遍歷結果:

[
  [3],
  [9,20],
  [15,7]
]

分析思路

常規思維法

我們理一遍題意:給定一棵二叉樹,把這棵二叉樹一層一層地訪問一遍,並且存儲在一個二維數組裏面。

這裏面的難點就是怎麽做到每次取一層的元素。

我們考慮使用隊列來存儲每一層的元素。為什麽使用隊列呢?因為對同一層的節點,先訪問,再把他們存儲到一個數組裏,存儲的順序要和訪問的順序一致,而隊列的特點就是先進先出

,和我們的要求一致,所以考慮使用隊列來實現本題。

算法如下:

  1. 首先,我們創建一個隊列,用來訪問節點(不一定是同一層);創建一個列表,用來存儲同一層的節點;創建一個二維列表,用來存儲最終的答案。

  2. 然後,先對根節點做處理,把根節點加入隊列,用列表存儲,在二維列表裏面加入剛才的列表,這樣,第一層節點就存儲好了。

  3. 到了第二層,我們再創建一個列表,用來存儲第二層的節點,並獲取一下隊列的長度,這裏隊列的長度是多少,接下來就要進行幾次循環,每次循環是訪問並存儲當前節點的左子節點和右子節點。
  4. 每次循環要做的工作是:彈出隊列頭部的一個節點,將這個節點的左子節點和右子節點加入隊列,並且把左子節點和右子節點的值存進剛才的列表。
  5. 若幹次循環完成後,隊列裏面就都是下一層的節點,列表已經存好了這一層的節點。
  6. 把列表加入二維列表。
  7. 重復第3~6步,直到隊列為空。

源碼

public List<List<Integer>> levelOrder (TreeNode root) {
    Queue<TreeNode> q = new LinkedList<>();
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    if (root == null)
        return ans;
    ((LinkedList<TreeNode>) q).add(root);
    list.add(root.val);
    ans.add(list);
    while (q.size() > 0) {
        list = new ArrayList<Integer>();
        int s = q.size();
        for (int i = 0; i < s; i++) {
            TreeNode tn = q.remove();
            if (tn.left != null) ((LinkedList<TreeNode>) q).add(tn.left);
            if (tn.right != null) ((LinkedList<TreeNode>) q).add(tn.right);
            if (tn.left != null) list.add(tn.left.val);
            if (tn.right != null) list.add(tn.right.val);
        }
        if (list.size() > 0) {
            ans.add(list);
        }
    }
    return ans;
}

註意,在第12行,一定要用一個整形數來存隊列的大小,不能直接在循環條件裏面使用i<q.size(),因為在循環體中,隊列大小是會變的,所以有必要用一個數來“固定”住這一層的隊列的長度。

遞歸法

在討論區還看到一種用遞歸的方法實現的,感覺十分巧妙,暫時就不解讀了,PO出來分享給大家。

// 遞歸法
public List<List<Integer>> levelOrder (TreeNode root) {
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    levelOrderHelper(ans,root,0);
    return ans;

}

private void levelOrderHelper (List<List<Integer>> ans, TreeNode root, int height) {
    if (root == null) return;
    if (height >= ans.size()) {
        ans.add(new ArrayList<Integer>());
    }
    ans.get(height).add(root.val);
    levelOrderHelper(ans, root.left, height + 1);
    levelOrderHelper(ans, root.right, height + 1);

}

102#二叉樹的層序遍歷