leetcode-daily/cpp/2205/220511-CN.cpp

211 lines
5.6 KiB
C++

#include <functional>
#include <cstdio>
#include <string>
#include <cstring>
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
explicit TreeNode(int x = 0, TreeNode* l = nullptr, TreeNode* r = nullptr) : val(x), left(l), right(r) {}
};
// Generic Tree
class CodecGeneric {
private:
static inline int digits(int x) {
if (!x)
return 1;
int r = 0;
for (; x; x /= 10)
++r;
return r;
}
static TreeNode* deHelp(const char* ptr, int len) {
if (!len)
return nullptr;
int val = 0;
std::sscanf(ptr, "%d", &val);
auto d = digits(val);
auto* ret = new TreeNode(val);
if (d == len)
return ret;
int L = 0;
ptr += d + 1; // value|
std::sscanf(ptr, "%d", &L);
ptr += digits(L) + 1; // len,
ret->left = deHelp(ptr, L);
int R = 0;
ptr += L + 1;
std::sscanf(ptr, "%d", &R);
ptr += digits(R) + 1;
ret->right = deHelp(ptr, R);
return ret;
}
public:
// Encodes a tree to a single string.
static std::string serialize(TreeNode* root) {
if (!root)
return {};
// value|len,leftTree|len,rightTree
std::string ret = std::to_string(root->val);
if (!root->left && !root->right)
return ret;
std::string l = serialize(root->left),
r = serialize(root->right);
ret.reserve(ret.length() + l.length() + r.length() + 16);
ret.append("|");
ret.append(std::to_string(l.length()));
ret.append(",");
ret.append(l);
ret.append("|");
ret.append(std::to_string(r.length()));
ret.append(",");
ret.append(r);
return ret;
}
// Decodes your encoded data to tree.
static TreeNode* deserialize(const std::string& data) {
if (data.empty())
return nullptr;
auto* ptr = data.c_str();
return deHelp(ptr, data.length());
}
};
class Base64 {
private:
inline static const char TABLE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
inline static const int REV_TABLE[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
public:
static std::string encode(const uint8_t* data, int len) {
std::string ret;
ret.reserve(int(len * 1.34) + 1);
int full = len / 3, trailing = len % 3;
for (int i = 0; i < full; ++i) {
int x = data[3 * i];
x = (x << 8) | data[3 * i + 1];
x = (x << 8) | data[3 * i + 2];
ret.push_back(TABLE[(x >> 18) & 63]);
ret.push_back(TABLE[(x >> 12) & 63]);
ret.push_back(TABLE[(x >> 6) & 63]);
ret.push_back(TABLE[x & 63]);
}
if (trailing) {
int x = int(data[len - 1]) << 8;
x = (trailing & 2) ? (x | (int(data[len - 2]) << 16)) : (x << 8);
ret.push_back(TABLE[(x >> 18) & 63]);
ret.push_back(TABLE[(x >> 12) & 63]);
ret.push_back((trailing & 2) ? TABLE[(x >> 6) & 63] : '=');
ret.push_back('=');
}
return ret;
}
static std::vector<uint8_t> decode(const char* data, int len) {
std::vector<uint8_t> ret;
ret.reserve(len / 1.3);
for (int i = 0; i < len - 4; i += 4) {
int x = (REV_TABLE[data[i]] << 18) | (REV_TABLE[data[1 + i]] << 12) | (REV_TABLE[data[2 + i]] << 6) | REV_TABLE[data[3 + i]];
ret.push_back((x >> 16) & 0xFF);
ret.push_back((x >> 8) & 0xFF);
ret.push_back(x & 0xFF);
}
int t = (data[len - 1] == '=') + (data[len - 2] == '=');
int x = (REV_TABLE[data[len - 4]] << 18) | (REV_TABLE[data[len - 3]] << 12) | (t > 1 ? 0 : (REV_TABLE[data[len - 2]] << 6)) | (t ? 0 : REV_TABLE[data[len - 1]]);
ret.push_back((x >> 16) & 0xFF);
if (t <= 1)
ret.push_back((x >> 8) & 0xFF);
if (!t)
ret.push_back(x & 0xFF);
return ret;
}
};
/**
* 449. Serialize and Deserialize BST
* Serialization is 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 a binary search tree. There is no restriction on how your serialization/deserialization algorithm should work. You need to ensure that a binary search tree can be serialized to a string, and this string can be deserialized to the original tree structure.
* The encoded string should be as compact as possible.
*/
class Codec {
private:
static void sHelp(TreeNode* r, std::vector<uint16_t>& s) {
s.push_back(r->val);
if (r->left)
sHelp(r->left, s);
if (r->right)
sHelp(r->right, s);
}
static TreeNode* dHelp(const uint16_t* x, int len) {
auto* ret = new TreeNode(*x);
if (len == 1)
return ret;
auto* nx = x + 1;
while (*nx < *x && nx - x < len)
++nx;
if (nx - x - 1)
ret->left = dHelp(x + 1, nx - x - 1);
if (nx - x < len)
ret->right = dHelp(nx, len - (nx - x));
return ret;
}
public:
// Encodes a tree to a single string.
static std::string serialize(TreeNode* root) {
if (!root)
return {};
std::vector<uint16_t> s;
sHelp(root, s);
return Base64::encode(reinterpret_cast<const uint8_t*>(s.data()), sizeof(uint16_t) * s.size());
}
// Decodes your encoded data to tree.
TreeNode* deserialize(const std::string& data) {
if (data.empty())
return nullptr;
auto x = Base64::decode(data.c_str(), data.length());
return dHelp(reinterpret_cast<const uint16_t*>(x.data()), x.size() / sizeof(uint16_t));
}
};
int main() {
Codec x;
auto ss = x.serialize(new TreeNode(2, new TreeNode(1), new TreeNode(3)));
auto rr = x.deserialize(ss);
return 0;
}