449. 序列化和反序列化二叉搜索树
题意
- 给定一棵二叉搜索树,实现序列化和反序列化;
- 注意 val 范围,因此 在序列化时需要插入分隔符分割每个节点的 val;
- 要善于利用 二叉搜索树的特性(中序遍历 = 递增排序);
解法
- 前序遍历 + 中序遍历 可以重构一棵树,又由于二叉搜索树自带中序遍历,因此在序列化时保存前序遍历;
- 由于节点的
val
不一定是个位数,所以要在序列化时插入分隔符; - 在反序列化时,首先分割字符串,得到前序遍历,然后通过前序遍历和中序遍历进行二叉搜索树的重构。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Codec {
public:void PreOrder(TreeNode* root, string& data){if(root == nullptr) return;data.append(to_string(root->val) + ","); // , 作为分隔符// if(root->left != nullptr) 递归函数开头就判断了非空的情况,因此这里不需要再次判断了PreOrder(root->left, data);// if(root->right != nullptr) 递归函数开头就判断了非空的情况,因此这里不需要再次判断了PreOrder(root->right, data);}// Encodes a tree to a single string.string serialize(TreeNode* root) {string res = "";PreOrder(root, res);return res;}vector<int> Split(string data) // 将序列化后的 string 进行分割,得到每个节点的 val{int idx = 0;int curS = 0;vector<int> ans;while(idx < data.size()){if(data[idx] == ','){string cur = data.substr(curS, idx - curS);ans.emplace_back(stoi(cur));curS = idx + 1;}idx++;}return ans;}TreeNode* ReconstructTree(vector<int> data, int s, int t){TreeNode* root = new TreeNode(data[s]);int rightIdx = -1;// 没有孩子if(s == t)return root;// 寻找右孩子的根for(int i = s + 1; i <= t; i++){if(data[i] > root->val){rightIdx = i;break;}}if(rightIdx == -1) // 没有右孩子{root->right = nullptr;// 构建左孩子root->left = ReconstructTree(data, s + 1, t);}else if(rightIdx == s + 1) // 没有左孩子{root->left = nullptr;// 构建右孩子root->right = ReconstructTree(data, s + 1, t);}else{// 有左孩子,构建左孩子和右孩子root->left = ReconstructTree(data, s + 1, rightIdx - 1);root->right = ReconstructTree(data, rightIdx, t);}return root;}// Decodes your encoded data to tree.TreeNode* deserialize(string data) {if(data == "") return nullptr;vector<int> intData = Split(data);TreeNode* root = ReconstructTree(intData, 0, intData.size()-1);return root;}
};// Your Codec object will be instantiated and called as such:
// Codec* ser = new Codec();
// Codec* deser = new Codec();
// string tree = ser->serialize(root);
// TreeNode* ans = deser->deserialize(tree);
// return ans;
复杂度
时间复杂度:O(N),序列化前序遍历每个节点,反序列化也是恢复每个节点;
空间复杂度:O(N),存储序列化后的字符串。