[LeetCode] 428. Serialize and Deserialize N-ary Tree N叉搜索樹的序列化和去序列化


 

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

Design an algorithm to serialize and deserialize an N-ary tree. An N-ary tree is a rooted tree in which each node has no more than N children. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that an N-ary tree can be serialized to a string and this string can be deserialized to the original tree structure.

For example, you may serialize the following 3-ary tree

as [1 [3[5 6] 2 4]]. Note that this is just an example, you do not necessarily need to follow this format.

Or you can follow LeetCode's level order traversal serialization format, where each group of children is separated by the null value.

For example, the above tree may be serialized as [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].

You do not necessarily need to follow the above suggested formats, there are many more different formats that work so please be creative and come up with different approaches yourself.

 

Constraints:

  • The height of the n-ary tree is less than or equal to 1000
  • The total number of nodes is between [0, 10^4]
  • Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless.
 

這道題讓我們對N叉樹進行序列化和去序列化,序列化就是將一個數據結構或物體轉化為一個位序列,可以存進一個文件或者內存緩沖器中,然后通過網絡連接在相同的或者另一個電腦環境中被還原,還原的過程叫做去序列化。現在讓我們來序列化和去序列化一個二叉樹,並給了我們例子。由於我們有了之前那道Serialize and Deserialize Binary Tree對二叉樹的序列化和去序列化的基礎,那么這道N叉樹的方法也是大同小異了。首先使用先序遍歷的遞歸解法,遞歸的寫法就十分的簡潔了,對於序列化,我們需要一個helper函數,里面首先判斷結點,若為空,則結果res加上一個井字符,否則加上當前結點值,跟一個空格,再加上子結點的個數值,再跟一個空格。之后就是遍歷子結點了,對每個子結點都調用遞歸函數即可。去序列函數需要用一個字符串流類來幫助讀字符,這個類是按空格來斷開字符串的,所以我們在序列化的時候中間都是用的空格。我們同樣需要一個helper函數,首先讀出結點值,如果讀出了井字號,直接返回空。否則繼續讀出子結點的個數,有了結點值我們就可以新建一個結點了,同時知道了子結點的個數,那么我們就循環調用遞歸函數相同的次數,將返回的子結點加入子結點數組即可,參見代碼如下:

 

解法一:

class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(Node* root) {
        string res;
        serializeHelper(root, res);
        return res;
    }
    
    void serializeHelper(Node* node, string& res) {
        if (!node) res += "#";
        else {
            res += to_string(node->val) + " " + to_string(node->children.size()) + " ";
            for (auto child : node->children) {
                serializeHelper(child, res);
            }
        }
    }

    // Decodes your encoded data to tree.
    Node* deserialize(string data) {
        istringstream iss(data);
        return deserializeHelper(iss);
    }
    
    Node* deserializeHelper(istringstream& iss) {
        string val = "", size = "";
        iss >> val;
        if (val == "#") return NULL;
        iss >> size;
        Node *node = new Node(stoi(val), {});
        for (int i = 0; i < stoi(size); ++i) {
            node->children.push_back(deserializeHelper(iss));
        }
        return node;
    }
};

 

我們還可以使用層序遍歷的迭代寫法,序列化的函數相對來說好一點,還是先判空,若為空,直接返回井字號。否則就使用隊列,加入根結點,然后就進行while循環,先取出隊首結點,然后res加入結點值,再加入空格,加入子結點個數,再加上空格。之后再把每一個子結點都加入隊列中即可。去序列化函數稍稍復雜一些,還是要用字符流類來讀取字符,需要用兩個隊列,分別來保存結點,和子結點個數。首先我們先取出結點值,如果是井字號,直接返回空。否則再取出子結點個數,我們先根據之前取出的結點值新建一個結點,然后加入結點隊列,把子結點個數加入個數隊列。然后就開始遍歷了,首先分別取出結點隊列和個數隊列的隊首元素,然后循環子結點個數次,再取出結點值,和子結點個數,如果其中某個值沒取出來,就break掉。根據取出的結點值新建一個結點,然后將結點值加入結點隊列,子結點個數加入個數隊列,然后將子結點加入子結點數組,參見代碼如下:

 

解法二:

class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(Node* root) {
        if (!root) return "#";
        string res;
        queue<Node*> q{{root}};
        while (!q.empty()) {
            Node *t = q.front(); q.pop();
            res += to_string(t->val) + " " + to_string(t->children.size()) + " ";
            for (Node *child : t->children) {
                q.push(child);
            }
        }
        return res;
    }

    // Decodes your encoded data to tree.
    Node* deserialize(string data) {
        istringstream iss(data);
        queue<Node*> qNode;
        queue<int> qSize;
        string val = "", size = "";
        iss >> val;
        if (val == "#") return NULL;
        iss >> size;
        Node *res = new Node(stoi(val), {}), *cur = res;
        qNode.push(cur);
        qSize.push(stoi(size));
        while (!qNode.empty()) {
            Node *t = qNode.front(); qNode.pop();
            int len = qSize.front(); qSize.pop();
            for (int i = 0; i < len; ++i) {
                if (!(iss >> val)) break;
                if (!(iss >> size)) break;
                cur = new Node(stoi(val), {});
                qNode.push(cur);
                qSize.push(stoi(size));
                t->children.push_back(cur);
            }
        }
        return res;
    }
};

 

類似題目:

Serialize and Deserialize BST 

Serialize and Deserialize Binary Tree

Encode N-ary Tree to Binary Tree

 

參考資料:

https://leetcode.com/problems/serialize-and-deserialize-n-ary-tree/

https://leetcode.com/problems/serialize-and-deserialize-n-ary-tree

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM