一、题目
331. 验证二叉树的前序序列化
这个题我写的有些复杂,但是很好理解。
二、分析
- 首先注意到,题目中非叶子节点,都有两个子节点,
#
或者数字,所以可以将两个连续的##
和一个数字相抵消成一个#
如果是一个正确的二叉树的前序序列化,那么这样消除,最后只剩下一个根节点:#
。
我用的栈进行操作。 - 要注意一些特殊情况:比如
"9,#,92,#,#"
。
我的做法首先将每个节点都暂存到vector中,当然也可以用split函数按逗号分隔。
9 3 4 # # 1 # # 2 # 6 # #
----- 入栈过程 ------
9 入栈, 3入栈, 4入栈, # 入栈
#,由于栈顶是#,将其出栈,可以和 4合并成一个#。
1 入栈, #入栈
#,由于栈顶是#,将其出栈,可以和1合并成一个#(a),但是合成之后,发现栈顶还是#(b),还要出栈,#(a)与#(b)与3,再次合成#。
...
最后栈中剩余一个#。
----- 栈元素变化 -----
9
9 3
9 3 4
9 3 4 # // 4## -> #
9 3 #
9 3 # 1
9 3 # 1 # // 1## -> # 3## -> #
9 #
9 # 2
9 # 2 #
9 # 2 # 6
9 # 2 # 6 # // 6## -> # 2## -> # 9## -> #
#
三、代码
class Solution {
public:
bool isValidSerialization(string preorder) {
stack<string> s1;
int n(preorder.length());
if(n <= 1){
if(n == 1 && preorder[0] == '#') return true;
return false;
}
// 将字符串中的节点值取出来
vector<string> vec;
string temp = "";
for (int i = 0; i < n; i++)
{
if (preorder[i] == ',')
{
vec.push_back(temp);
temp = "";
continue;
}
if (i == n - 1)
{
temp += preorder[i];
vec.push_back(temp);
break;
}
temp += preorder[i];
}
n = vec.size();
//开始入栈检查前序
for(int i = 0; i < n; i++){
if(vec[i] != "#"){
s1.push(vec[i]);
}else{
//遇到#时,如果栈顶不是#,直接入栈
if(s1.empty() || s1.top() != "#"){
s1.push("#");
}else{
//如果栈顶是#,则需要每次出栈一个 # 和一个 not#
//直到栈顶不是 # 或者空,也就是从叶子节点找到了暂时的 not# 父节点
while(!s1.empty() && s1.top() == "#"){
s1.pop(); // #
// 如果出栈的过程中直接空了,返回错误
if(s1.empty()) return false;
s1.pop(); // not #
}
s1.push("#");
}
}
}
//最后判断栈中元素唯一,且为 #
if(!s1.empty()){
s1.pop();
if(s1.empty()) return true;
}
return false;
}
};
···
执行用时:4 ms, 在所有 C++ 提交中击败了74.27%的用户
内存消耗:10.8 MB, 在所有 C++ 提交中击败了5.07%的用户