記事のディレクトリ
1.ソースのタイトル
リンク:バイナリツリーの順序
出典:LeetCode--「安全-Offerを証明する」特別
0002タイトル
二つの機能は、バイナリツリーをシリアライズとデシリアライズするために使用されて実装します。
例:
あなたは以下のバイナリツリーを使用することができます。
1 / \ 2 3 / \ 4 5
"[1,2,3、NULL、NULL、4,5]" としてシリアライズ
3.解決のタイトル
方法:シーケンス反復法トラバーサル+
これは、あるHard
アイデアは、まだ47、48受信上のデータ処理や最終テストの文字列の挑戦は非常に明確である、という問題があります。
- バイナリツリートラバーサルシーケンスを使用してシーケンス。一意のバイナリツリーを識別されていないレベルを横切ります。あなたは空のノードとノードが発生した場合
'#'
を表します。各ノードのバックを追加','
エンドを表し、あなたは一意のバイナリツリーを識別することができます。 - 階層的なシーケンスのバイナリツリーを与えるために、上記
1,2,3,#,#,4,5,#,#,#,#,
- そして、この配列に基づいて、デシリアライズ。(陰性判定の場合に注意してください)
ピットについての私の話は、それに遭遇しました:
- まず、時間順に、直接使用することはできません
string
でpush_back
の方法、かかる場合がありますテストケース47、48にハードである+=
文字列の形式を、それを使用することができる文字ストリームの形で - 単に即ちだけでなく、追加、階層的方法のシーケンスを使用しない
#
一つは一意のバイナリツリーは、ツリーノード値を決定できませんでしたこれを行うために、文字列を分割するval
10を超えると、直接正常除去する方法がないval
値があるため、#12#
あいまいさ、私は最終的には知らないです1、2
、まだ12
- 状況は、負のノードが対処する必要があり、これは確かに無視し始めています
- 最後尾
#
削除する必要があり、これは考えることは非常に簡単です
基本的には上記の点で大きなピットがに求めるメッセージが表示され、それは本当にHard
簡単で、一般的ではありません... dfs、bfs
私はちょうど私の全体の気性を置きます...
バート・ソリューション1
私はいなかった...ここで成形しているので、冷却書くには若すぎる思考val
にchar
タイプなので、string
ビットにケースを取る直接撮影することができます。
以下のコードを参照してください。
// 没 AC,样例 47/48 过不去
// [1,null,2,null,3,null,4,null,5,null,6,null,...,999,null,1000] 单支树,IO极其密集
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string s;
queue<TreeNode*> q;
if (root) q.push(root);
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (t) {
s.push_back(t->val); // 过不去,string 爆掉了
q.push(t->left);
q.push(t->right);
} else {
s.push_back('#');
}
}
return s;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int cnt = data.find_last_not_of('#');
if (cnt != std::string::npos)
data.erase(cnt + 1);
else
data.clear();
if (data.empty()) return nullptr;
queue<TreeNode*> q;
string val(data);
TreeNode *res = new TreeNode(val[0]), *cur = res;
q.push(cur);
int i = 1;
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (i > val.size() - 1) break;
if (val[i] != '#') {
cur = new TreeNode(val[i]);
q.push(cur);
t->left = cur;
++i;
}
else {
++i;
}
if (i > val.size() - 1) break;
if (val[i] != '#') {
cur = new TreeNode(val[i]);
q.push(cur);
t->right = cur;
++i;
}
else {
++i;
}
}
return res;
}
};
2悪いソリューション
文字列への流れを操作することが適切にテストケース47を読み取ることができるので、文字が読み取られ、あろう整数123
に分割1
2
3
以降では、3つの文字、string [ ]
出力整数を完了できない動作は、それが与えられています。文字列を追加しなくてものみ文字列処理と、しかし#
、文字列分割に固有に二分木、ツリーノード値を識別する方法val
10を超えると、直接正常除去する方法がないval
ので、値を#12#
なし、曖昧さが最終的に知っているがされ1、2
、まだ12
、その一意のバイナリツリーを識別考慮すべき!
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
stringstream ss;
while (!q.empty()) {
root = q.front();
q.pop();
if (root) {
q.push(root->left);
q.push(root->right);
ss << root->val;
}
else {
ss << '#';
}
}
string data = ss.str();
return data;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int cnt = data.find_last_not_of('#');
if (cnt != std::string::npos)
data.erase(cnt + 1);
else
data.clear();
if (data.empty()) return nullptr;
queue<TreeNode*> q;
string val(data);
TreeNode *res = new TreeNode(val[0] -'0'), *cur = res;
q.push(cur);
int i = 1;
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (i > val.size() - 1) break;
if (val[i] != '#' && i < val.size() - 1) {
string tmp;
while (i < val.size() && val[i] != '#' ) {
tmp += val[i];
++i;
}
cur = new TreeNode(stoi(tmp));
q.push(cur);
t->left = cur;
}
else {
++i;
}
if (i > val.size() - 1) break;
if (val[i] != '#') {
string tmp;
while (i < val.size() && val[i] != '#') {
tmp += val[i];
++i;
}
cur = new TreeNode(stoi(tmp));
q.push(cur);
t->right = cur;
}
else {
++i;
}
}
return res;
}
};
成功版
これらの問題を取り除く、その後、負の数の問題を解決するために、この問題を取得します!
以下のコードを参照してください。
// 执行用时 :8 ms, 在所有 C++ 提交中击败了84.14%的用户
// 内存消耗 :10 MB, 在所有 C++ 提交中击败了100.00%的用户
/**
* 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 {
private:
string encode(TreeNode* root) {
if (!root) return "#,";
string res = "";
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (t) {
res += to_string(t->val) + ",";
q.push(t->left);
q.push(t->right);
} else {
res += "#,";
}
}
return res;
}
TreeNode* takeNum(const string& data, int& p) {
if (data[p] == '#') {
p += 2;
return NULL;
}
bool isN = false;
if (data[p] == '-') {
isN = true;
p++;
}
int val = 0;
while (data[p] != ',') {
val = val * 10 + (data[p] - '0');
p++;
}
p++;
if (isN) {
val = -val;
}
return new TreeNode(val);
}
TreeNode* decode(const string& data) {
if (data[0] == '#') return NULL;
int p = 0;
TreeNode *root = takeNum(data, p);
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
TreeNode *l = takeNum(data, p);
TreeNode *r = takeNum(data, p);
if (l) q.push(l);
if (r) q.push(r);
t->left = l;
t->right = r;
}
return root;
}
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string s = encode(root);
return s;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
TreeNode *root = decode(data);
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
方法2:前順再帰的ソリューション+
入力及び出力ストリームを介して文字列istringstream
とostringstream
。
- ノードは、出力文字列に格納され、その後、現在の値が存在する場合にシリアライズするために、ルートから開始し、各関数が再帰的に、その左右の子ノードにシリアル化することができます。
- 直列化のために行く、最初のルートノードを生成するための最初の文字を、読み、その後、再帰的にルートノードの左と右の子ノードに機能をシリアル化するために呼び出します
- または、明らかに単純な再帰の多くは、問題の詳細に対処し、ほとんど上記、繰り返すことはしませんが、
以下のコードを参照してください。
// 执行用时 :40 ms, 在所有 C++ 提交中击败了63.53%的用户
// 内存消耗 :26.5 MB, 在所有 C++ 提交中击败了100.00%的用户
/**
* 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:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
ostringstream out;
serialize(root, out);
return out.str();
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
istringstream in(data);
return deserialize(in);
}
private:
void serialize(TreeNode *root, ostringstream &out) {
if (root) {
out << root->val << ' ';
serialize(root->left, out);
serialize(root->right, out);
} else {
out << "# ";
}
}
TreeNode* deserialize(istringstream &in) {
string val;
in >> val;
if (val == "#") return nullptr;
TreeNode *root = new TreeNode(stoi(val));
root->left = deserialize(in);
root->right = deserialize(in);
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));