Given an n-ary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).
For example, given a 3-ary
tree:
We should return its level order traversal:
[ [1], [3,2,4], [5,6] ]
Note:
- The depth of the tree is at most
1000
. - The total number of nodes is at most
5000
.
這道題給了我們一棵N叉樹,讓我們對其進行層序遍歷。我們做過之前二叉樹的層序遍歷的那道題的話Binary Tree Level Order Traversal,那么這道題也就不難了。雖說現在每一個結點可能有很多個子結點,但其實處理的思路的都是一樣的。子結點放到了一個children數組中,我們訪問的時候只要遍歷數組就行了。先來看迭代的寫法,用到了隊列queue來輔助,首先判斷root是否為空,為空直接返回空數組,否則加入queue中。然后遍歷queue,這里用的trick就是,要加個for循環,要將當前queue中的結點的個數統計下來,因為再加入下一層的結點時,queue的結點個數會增加,而在加入下一層結點之前,當前queue中的結點個數全都屬於一層,所以我們要把層與層區分開來,將同一層的結點都放到一個數組out中,之后再放入結果res中,這種層序遍歷的思想在迷宮遍歷找最短路徑的時候應用的也很多,是個必須要掌握的方法呢,參見代碼如下:
解法一:
class Solution { public: vector<vector<int>> levelOrder(Node* root) { if (!root) return {}; vector<vector<int>> res; queue<Node*> q{{root}}; while (!q.empty()) { vector<int> out; for (int i = q.size(); i > 0; --i) { auto t = q.front(); q.pop(); out.push_back(t->val); if (!t->children.empty()) { for (auto a : t->children) q.push(a); } } res.push_back(out); } return res; } };
下面再來看遞歸的寫法,其實層序遍歷天然適合迭代的寫法,但我們強行遞歸也是可以的,就是有點秀。由於遞歸DFS的設定是一條路走到黑再返回,那么必然會跨越不同的層數,所以為了區別當前的層,我們需要一個變量level來標記當前的層數,根結點root就是第0層,依此類推往上加。然后還有個trick就是關於結果res的大小,由於我們並不知道樹的深度,所以一旦我們遍歷的層數超過了當前res的大小,我們需要resize一下,這樣才不會出錯。之后,我們將當前遍歷到的結點加到res中的第level層中,然后遍歷子結點數組,對每一個子結點調用遞歸函數即可,參見代碼如下:
解法二:
class Solution { public: vector<vector<int>> levelOrder(Node* root) { vector<vector<int>> res; helper(root, 0, res); return res; } void helper(Node* node, int level, vector<vector<int>>& res) { if (!node) return; if (res.size() <= level) res.resize(res.size() + 1); res[level].push_back(node->val); for (auto a : node->children) { helper(a, level + 1, res); } } };
類似題目:
Binary Tree Level Order Traversal
N-ary Tree Preorder Traversal
N-ary Tree Postorder Traversal
參考資料:
https://leetcode.com/problems/n-ary-tree-level-order-traversal/description/