mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
3.5 KiB
3.5 KiB
331. Verify Preorder Serialization of a Binary Tree
思路
题目给定一个字符串,判断这个字符串能否表示成一个二叉树。
字符串中每个节点用逗号分割,所以我们可以先用istringsteam
将这个字符串转换成输入流,然后用getline
并设置分隔符delim为逗号(默认是换行符)不断获得每个节点node。
istringstream in(preorder);
string node;
while(getline(in, node, ',')){
.....
}
思路一
这题的分类是栈,我们可以用栈解决,参考讨论区。
开辟一个栈,然后不断检查获得的节点node,有两种情况:
- node为一个数,说明接下来会开辟一个以这个节点为根的子树,所以我们将其压栈;
- node为#,此时根据栈顶划分又有两种情况:
2.1 栈顶为一个数,说明当前的#为左空节点,压栈就可以了(等待它的兄弟)。
2.2 栈顶为#,说明当前#为右空节点,栈顶为其左兄弟,应该出栈两次将其左兄弟及父亲删除,
然后回到第2.1开始不断循环,直到栈顶为一个数或者栈空,最后才将当前#入栈。
2.2中出栈两次是连贯的过程,所以如果第一次出栈后栈就空了则可以直接返回false。检查完毕后,如果栈中只剩下一个元素且就为#即可返回true,否则返回false。
以"9,3,4,#,#,1,#,#,2,#,6,#,#"为例的话上述过程如下图所示:
时空复杂度均为O(n)。
思路二
看讨论区发现有一个不用栈的方法,常数时间复杂度。
在二叉树中,如果把空节点#当做是叶子,那么
- 所有非空节点有2个出度1个入度(除了根节点);
- 所有空节点(即#)有0个出度1个入度。
我们维持一个变量diff代表 出度减去入度,初始为1(因为根节点入度为0而不是1)。遇到当前节点node时,先将diff减去1(因为不管node是否为空都有1个入度),
如果非空(即不是#),那还应该将diff加上2。这个过程中如果一旦遇到diff小于0则可返回false,最后返回 diff==0
。
时间复杂度O(n), 空间复杂度O(1)。
C++
思路一
class Solution {
public:
bool isValidSerialization(string preorder) {
istringstream in(preorder);
string node;
stack<char>stk;
while(getline(in, node, ',')){
if(node != "#") stk.push('n');
else{
while(!stk.empty() && stk.top() == '#'){
stk.pop();
if (stk.empty()) return false;
stk.pop();
}
stk.push('#');
}
}
return stk.size() == 1 && stk.top() == '#';
}
};
思路二
class Solution {
public:
bool isValidSerialization(string preorder) {
istringstream in(preorder);
string node;
int diff = 1;
while(getline(in, node, ',')){
if (--diff < 0) return false;
if (node != "#") diff += 2;
}
return diff == 0;
}
};