# N-ary Tree ###### tags: `LeetCode筆記` ## :memo: 一、Definition If a tree is a rooted tree in which each node has no more than **N** children, it is called **N-ary tree**. ![](https://i.imgur.com/j9ehXTE.png) ## :memo: 二、Traversal ### 1. Preorder Traversal A->B->C->E->F->D->G #### C ``` void traverse(int* ret, int* index, struct Node* root) { if (root == NULL) { return NULL; } ret[*index] = root->val; (*index)++; for (int i = 0; i < root->numChildren; i++) { if (root->children[i] != NULL) { traverse(ret, index, root->children[i]); } } } int* preorder(struct Node* root, int* returnSize) { int* ret = (int*) malloc(sizeof(int) * 10000); int index = 0; traverse(ret, &index, root); *returnSize = index; return ret; } ``` #### C++ ``` class Solution { public: void preorder_traverse(Node* root, vector<int>& res) { if (root == nullptr) { return; } res.push_back(root->val); for (int i = 0; i < (root->children).size(); i++) { preorder_traverse(root->children[i], res); } } vector<int> preorder(Node* root) { vector<int> res; preorder_traverse(root, res); return res; } }; ``` #### C++ with stack ``` class Solution { public: vector<int> preorder(Node* root) { if (!root) { return {}; } Node* temp = root; stack<Node*> s; vector<int> res; s.push(temp); while (!s.empty()) { temp = s.top(); if (!temp->children.empty()) { res.push_back(s.top()->val); s.pop(); for (int i = temp->children.size() - 1; i >= 0; i--){ s.push(temp->children[i]); } } else { res.push_back(s.top()->val); s.pop(); } } return res; } }; ``` ### 2. Postorder Traversal B->E->F->C->G->D->A #### C ``` void traverse(int* ret, int* index, struct Node* root) { if (root == NULL) { return; } for (int i = 0; i < root->numChildren; i++) { if (root->children[i] != NULL) { traverse(ret, index, root->children[i]); } } ret[*index] = root->val; (*index)++; } int* postorder(struct Node* root, int* returnSize) { int* ret =(int*) malloc(sizeof(int) * 10000); int index = 0; traverse(ret, &index, root); *returnSize = index; return ret; } ``` #### C++ ``` class Solution { public: void postorder_trverse(Node* root, vector<int>& res) { if (root == nullptr) { return; } for (int i = 0; i < (root->children).size(); i++) { postorder_trverse(root->children[i], res); } res.push_back(root->val); } vector<int> postorder(Node* root) { vector<int> res; postorder_trverse(root, res); return res; } }; ``` ### 3. Level-order Traversal A->B->C->D->E->F->G #### C with recursion ``` int maxHeight(struct Node* root) { if (root == NULL) { return 0; } if (root->numChildren == 0) { return 1; } int max = 0; for (int i = 0; i < root->numChildren; i++) { int tmp = maxHeight(root->children[i]) + 1; max = tmp > max? tmp : max; } return max; } void traverse(struct Node* root, int** ret, int ridx, int** returnColumnSizes) { if (root == NULL) { return; } ret[ridx][(*returnColumnSizes)[ridx]] = root->val; (*returnColumnSizes)[ridx]++; for (int i = 0; i < root->numChildren; i++) { traverse(root->children[i], ret, ridx + 1, returnColumnSizes); } } int** levelOrder(struct Node* root, int* returnSize, int** returnColumnSizes) { int Height = maxHeight(root); *returnSize = Height; *returnColumnSizes = (int*)calloc(Height,sizeof(int)); int** ret = (int**)malloc(Height*sizeof(int*)); for(int i=0;i<Height;i++) { ret[i] = (int*)malloc(sizeof(int)*10000); } traverse(root,ret,0,returnColumnSizes); return ret; } ``` #### C++ BFS using a Queue ``` class Solution { public: vector<vector<int>> levelOrder(Node* root) { if (root == nullptr) { return {}; } vector<vector<int>> res; queue<Node*> q; vector<int> temp; temp.push_back(root->val); res.push_back(temp); q.push(root); while (!q.empty()) { int Q_size = q.size(); vector<int> temp; for (int i = 0; i < Q_size; i++) { Node* curr = q.front(); q.pop(); for (int j = 0; j < curr->children.size(); j++) { if (curr->children[j] != nullptr) { temp.push_back(curr->children[j]->val); q.push(curr->children[j]); } } } res.push_back(temp); } res.pop_back(); return res; } }; ``` ### Note: there is no standard definition for in-order traversal in n-ary trees. ## :memo: Maximum Depth of N-ary Tree (Easy) ![](https://i.imgur.com/3eeyVVW.png) ![](https://i.imgur.com/aGaDyAt.png) ### 作法 檢查children的size,0就回傳1,非0就繼續遞迴 ``` class Solution { public: int maxDepth(Node* root) { if (root == nullptr) { return 0; } if (root->children.size() == 0) { return 1; } int res = INT_MIN; for (int i = 0; i < root->children.size(); i++) { res = max(maxDepth(root->children[i]) + 1, res); } return res; } }; ``` ## :memo: Encode N-ary Tree to Binary Tree (Hard) ![](https://i.imgur.com/SJhSepu.png) ### 作法 C++ ``` class Codec { public: // Encodes an n-ary tree to a binary tree. TreeNode* encode(Node* root) { //left child: child chain, right child: lower siblings if (root == NULL) return NULL; TreeNode* ret = new TreeNode(root->val); if (root->children.size() == 0) return ret; ret->left = encode(root->children[0]); TreeNode* now = ret->left; for (int i = 1; i < root->children.size(); i++) { now->right = encode(root->children[i]); now = now->right; } return ret; } // Decodes your binary tree to an n-ary tree. Node* decode(TreeNode* root) { if (root == NULL) return NULL; Node* ret = new Node; ret->val = root->val; TreeNode* now = root->left; while(now) { ret->children.push_back(decode(now)); now = now->right; } return ret; } }; ``` ## :memo: Serialize and Deserialize N-ary Tree (Hard) https://leetcode.com/problems/serialize-and-deserialize-n-ary-tree/description/ ### 作法 C++ ``` class Codec { public: //rule: root, number of child, each child // Encodes a tree to a single string. string serialize(Node* root) { string s; encode_dfs(root, s); return s; } void encode_dfs(Node* root, string& s) { if(!root) return; s += " " + to_string(root->val) + " " + to_string(root->children.size()); for (auto p: root->children) encode_dfs(p, s); } // Decodes your encoded data to tree. Node* deserialize(string data) { stringstream ss(data); return decode(ss); } Node* decode(stringstream& ss) { ss.peek(); if (ss.eof()) return nullptr; auto root = new Node(); int child_size; ss >> root->val >> child_size; for (int i = 0; i < child_size; i++) root->children.push_back(decode(ss)); return root; } }; ``` ## :memo: 刷題檢討 學會**基本traversal**和**算高度**,難題用C++去解: 1. 多子樹與二元樹轉換 2. 解析多子樹