トピック:
二分木をシリアル化する1つの方法は、プレオーダートラバーサルを使用することです。空でないノードに遭遇した場合、このノードの値を記録できます。空のノードの場合は、#などのタグ値レコードを使用できます。
たとえば、上記の二分木は文字列「9,3,4、#、#、1、#、#、2、#、6、#、#」にシリアル化できます。ここで、#は空のノードを表します。
カンマ区切りのシーケンスを指定して、それがバイナリツリーの正しいプレオーダーシリアル化であることを確認します。ツリーを再構築せずに実行可能なアルゴリズムを記述します。
コンマで区切られた各文字は、整数またはヌルポインターを表す「#」のいずれかです。
入力形式は常に有効であると考えることができます。たとえば、「1、、3」のように2つの連続したコンマが含まれることはありません。
ソース:
問題解決のアイデア1:スタック
質問を読んだ後、少し混乱しました。質問の例を注意深く調べたところ、#はすべてリーフノードであり、番号はすべて非リーフノードであることがわかりました。
決定の考え方は次のとおりです:#スタックをプルし、番号をスタックにプッシュします
デジタルノードの子の数を格納するスタックを定義します。デジタルノードには2つの子が必要です。すべてのノードをループします。
- ノードが#の場合、スタックは空の場合は終了します。それ以外の場合は、スタックの最上位要素に子が追加されます。
- ノードが数値の場合、スタックが空の場合はスタックに直接プッシュされます。それ以外の場合は、スタックの最上位要素に子を追加した後にスタックにプッシュされます。
- スタックの最上位ノードが2つの子を満たすと、スタックは空になるか、スタックの最上位ノードが2つの子に対して十分でなくなるまでポップされます。
スタックが空で、背後にノードがない場合、trueを返し、その他はfalseを返します。
コードは次のとおりです(少し混乱します):
class Solution {
public:
bool isValidSerialization(string preorder) {
stack<int> st;
int i = 0;
while (i < preorder.size()) {
char ch = preorder[i];
while (i < preorder.size() && preorder[i] != ',') i++;
i++;
if (ch == '#') {
if (st.empty()) break;
// top++
int t = st.top();
st.pop();
st.push(t+1);
} else {
// top++
if (!st.empty()) {
int t = st.top();
st.pop();
st.push(t+1);
}
st.push(0);
}
bool end = false;
while (st.top() == 2) {
st.pop();
if (st.empty()) {
end = true;
break;
}
}
if (end) break;
}
return st.empty() && i >= preorder.size();
}
};
問題解決のアイデア2:ノードの性質を使用する
すべての非リーフノードには2つの子が必要であるため、満たす必要があります。リーフノードには非リーフノードより1つ多い必要があります。この質問では、#nodeはnumberノードより1多いです。
この性質に基づいたコードの記述は簡単です。カウントcnt = 1を定義し、#が-の場合、数値が++の場合、カウントが0の場合、終了し、終了後にノードが存在するかどうかを判断します。未来。
int isValidSerialization(char * preorder){
int cnt = 1;
char *p = preorder;
while (*p != 0) {
if (*p == '#') {
cnt--;
} else {
cnt++;
}
while (*p != 0 && *p != ',') p++;
if (*p == ',') p++;
if (cnt == 0) break;
}
return cnt == 0 && *p == 0;
}