leetcode 第297題 二叉樹的序列化與反序列化
題目分析
題目(傳送門)如下:
題目的意思是讓設計一個類,類中的一個方法能夠將數轉化成字符串,另一個方法就是將生成的字符串復原成樹。類似的題目還有449. 序列化和反序列化二叉搜索樹 。不過第449題好做一點,因爲是二叉搜索樹,所以我們可以先得到中序遍歷得結果,然後將中序遍歷排序就可以得到先序遍歷結果,最後就可以根據先序遍歷和中序遍歷復原二叉樹。
序列化
本題要稍微複雜點,因爲是任意一個樹,所以不能使用上述的方法。換種思路,我們可以選擇廣度優先遍歷。首先是序列化,即將樹轉換成字符串。
上圖是給定的一個樹以及其序列化後的結果,這裏我的方法是將所有存在的節點的左右子樹全部納入到了返回字符串中,其中空的節點用 # 來表示的。這個序列化過程不難,主要就是樹的廣度優先遍歷的結果。有一點注意,就是每次得到一層的節點列表時,先檢查一下是否全部的節點爲都爲#,如果是這樣就說明整個樹遍歷結束了,就可以直接返回了。
反序列化
序列化的過程不難,主要是反序列化,即將上面的字符串復原成樹。
首先,先生成一個節點列表,與字符串中的數字位置對應,並且#生成None。
由於我們序列化字符串的特點,每一個不爲空的節點,其必然有兩個左右孩子(不管孩子是否爲空),這是一定成立的。而且我們知道根節點是存在的(假設根節點不爲空,爲空就直接返回),那麼第二層就有兩個節點,在我們例子中,第二層節點都是存在的,那麼第三層有四個節點,而第三層四個節點中只有兩個節點是存在的,所有第四層也只有四個節點。以上規律反映到我們節點列表的下標中就是:下標0爲第一層,下標1~ 2爲第二層,下標3 ~ 6是第三層的,下標 7 ~ 10是第四層的。所以我們就可以遍歷節點列表,將節點左右節點一一找出。
首先,節點1爲第一層,節點2,3爲第二層,那麼節點1的左右節點一定是節點2,3。
同樣節點2,3的左右孩子分別爲下標3 ~ 6的四個節點。
最後,由於下標爲3,4的節點爲空節點,所以額可以直接跳過,到最後就是節點4,5,同樣後面的四個節點就是他們的左右節點。
至此,就已經復原了整個二叉樹,最後只要返回節點1就好了。
源碼
Python
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
ret = []
if root:
nodes = [root]
while nodes:
temp = []
for node in nodes:
if node:
ret.append(node.val)
temp += [node.left, node.right]
else:
ret.append(None)
if temp.count(None) == len(temp):
break
nodes = temp
return ",".join(map(str, ret))
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
if data:
nodes = [TreeNode(int(i)) if i != 'None' else None for i in data.split(',')]
print(nodes)
n = len(nodes)
end = 1
start = 0
while True:
if end >= n:
break
nextLevel = end
for node in nodes[start:end]:
if node:
node.left = nodes[nextLevel]
node.right = nodes[nextLevel+1]
nextLevel += 2
start = end
end = nextLevel
return nodes[0]
return None
C++
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Codec {
public:
string serialize(TreeNode* root) {
string ret;
vector<TreeNode*> nodes;
vector<TreeNode*> temp;
if (root) {
nodes.push_back(root);
while (!nodes.empty()) {
for (auto node : nodes) {
if (node) {
temp.push_back(node->left);
temp.push_back(node->right);
ret.append(to_string(node->val));
}
else
ret.push_back('#');
ret.push_back(',');
}
int count = 0;
for (auto node : temp) {
if (node) ++count;
}
if (!count) break;
nodes = temp;
temp.clear();
}
ret.pop_back();
}
return ret;
}
TreeNode* deserialize(string data) {
if (!data.empty()) {
vector<TreeNode*> nodes;
stringstream input(data);
string temp;
while (getline(input, temp, ',')){
if (temp != "#") nodes.push_back(new TreeNode(stoi(temp)));
else nodes.push_back(nullptr);
}
int start = 0, end = 1, n = nodes.size();
int next = end;
while (1) {
if (end >= n) break;
for (int i = start; i < end; ++i) {
if (nodes[i]) {
nodes[i]->left = nodes[next];
nodes[i]->right = nodes[next + 1];
next += 2;
}
}
start = end;
end = next;
}
return nodes[0];
}
return nullptr;
}
};