题解 | #序列化二叉树#
序列化二叉树
https://www.nowcoder.com/practice/cf7e25aa97c04cc1a68c8f040e71fb84
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
#include <cstddef>
#include <cstring>
class Solution {
public:
char* Serialize(TreeNode* root) {
if (root == nullptr) return "#";
deque<TreeNode*> deq;
deq.push_back(root);
string res;
int i = 1, num_count = 0, num_null_prev = 0, num_null_cur = 0;
//层序遍历,数字之间使用!间隔,nullptr用#表示,先构建一个deque列表
while (!deq.empty()) {
TreeNode* temp = deq.front();
deq.pop_front();
if (temp != nullptr) {
num_count++;
res += to_string(temp->val) + "!";
deq.push_back(temp->left);
deq.push_back(temp->right);
} else {
num_null_cur++;
res += '#';
}
//判断是第几层,该层是否已经满了。
//i表示第i层,判断是否满足2^(i-1)=上一层nullptr的个数*2+当前层数字个数+当前层nullptr的个数,满足时当前层满了
//之前都没有空结点
if (num_null_prev == 0) {
//当前层满了
if (num_count + num_null_cur == pow(2, i - 1)) {
i++;
//到下一层的时候需要更新数值
num_count = 0;
num_null_prev = num_null_cur;
num_null_cur = 0;
}
} else {
//当前层满了
if (2 * num_null_prev + num_null_cur + num_count == pow(2, i - 1)) {
i++;
num_count = 0;
//前一层空结点个数 = 前一层空结点个数*2+当前层空结点个数
num_null_prev = num_null_cur + 2 * num_null_prev;
num_null_cur = 0;
}
}
}
//最后的叶结点添加了2个nullptr进入deque中,多算了一层;在公式中又多加了一层,所以是减2
i -= 2;
//!的位置为终点的位置,计算长度(长度为终点位置+1),char*数组需在长度的基础上再+1,因为要加终止符
int pos = res.find_last_of('!');
char* res_ptr = new char[pos + 2];
res = res.substr(0, pos + 1);
strcpy(res_ptr, res.c_str());
res_ptr[pos + 1] = '\0';
return res_ptr;
}
TreeNode* Deserialize(char* str) {
if (str == nullptr) return nullptr;
deque<TreeNode*> deq1, deq2;
string val;
//构建两个队列,第一个队列为父结点,第二个队列为子节点,第二个队列删去根结点。
for (int i = 0; str[i] != '\0'; i++) {
if (isdigit(str[i])) {
val += str[i];
} else if (str[i] == '!') {
TreeNode* temp = new TreeNode(atoi(val.c_str()));
deq1.push_back(temp);
deq2.push_back(temp);
val.clear();
} else {
deq1.push_back(nullptr);
deq2.push_back(nullptr);
}
}
deq2.pop_front();
TreeNode* root = deq1.front(), *cur = root;
//当取出一个非空父结点时,对应取出两个子节点;空的父结点跳过。当子节点的deque为空时,结束循环
while (deq2.size() != 0) {
cur = deq1.front();
deq1.pop_front();
if (cur != nullptr) {
//判断子节点列表是否为空,空则跳出循环
if (deq2.size() == 0) break;
cur->left = deq2.front();
deq2.pop_front();
//判断子节点列表是否为空,空则跳出循环
if (deq2.size() == 0) break;
cur->right = deq2.front();
deq2.pop_front();
}
}
return root;
}
};

查看9道真题和解析