最近自己的学长面试的时候遇到这一道题了,然后把这道题出给了我。我的第一想法是根据前序遍历建立一个树结构,然后根据能否建立树来判断。但是题目要求不能重建树,所以自己确实不会做。在网上看了别人的解答才恍然大悟!这里总结一下大神们的解法。
首先我们肯定要用istringstream来操作字符串,C++里面没有像Java那样有字符串的split函数(可以直接分割任意字符串);在C++里我们只能用getline这个函数从用户处获得字符,将字符串流的内容都存到一个vector数组中。我们可以先看一个简单的例子:
int main()
{
istringstream in("a,b,c,d,e,d,f");
string t = "";
while (getline(in, t, ','))
{
cout << t;
Sleep(100);
}
system("pause");
return 0;
}
istringstream类用于执行C++风格的串流的输入操作。
ostringstream类用于执行C风格的串流的输出操作。
strstream类同时可以支持C风格的串流的输入输出操作。
这个函数是从string对象中读取字符到in中,然后在执行while (getline(in, t, ‘,‘))
的时候表示遇到‘,‘就将已经读到的字符输出。上面的代码输出的结果为
abcdedf
通过仔细观察我们可以发现两个规律:1.数字的个数总是比#号少一个;2.最后一个一定是#号。
所以我们可以根据这两个规律,将最后一个字符“#”单独进行考虑,那么此时数字的个数和#的个数应该相同。所以可以初始化一个计数器专门记录数字的个数,当遇到数字则计数器+1,遇到#号-1;这样遍历到除了最后一个字符,则一定会有计数器=0!。所以最后遍历完的判断就是计数器是否等于0与最后一个字符是不是#。
当然还有一些小细节要处理,比如“#,9,3,4,#”与“9,3,#,#,#,1”这两个错误案例,根节点首先不能为#,同时要确保在[0,i]这个范围内#的个数是不大于数字的个数的。所以可以通过在循环中判断是否会有计数器小于0的情况,代码如下:
class Solution {
public:
bool isValidSerialization(string preorder) {
istringstream in(preorder);
string t="";
int cnt=0;
while(getline(in,t,','))
v.push_back(t);
for(int i=0;i<v.size()-1;i++)
{
if(v[i]=="#")
{
if(cnt==0)
return false;
cnt--;
}
else
cnt++;
}
return cnt==0 && v.back()=="#";
}
private:
vector<string> v;
};
解法二是边解析边判断,遇到不合题意的情况直接返回false,而不用全部解析完再来验证是否合法,提高了运算的效率。
class Solution {
public:
bool isValidSerialization(string preorder) {
istringstream in(preorder);
string t = "";
int degree = 1;
bool degree_is_zero = false;;
while (getline(in, t, ',')) {
if (degree_is_zero) return false;
if (t == "#") {
if (--degree == 0) degree_is_zero = true;
} else ++degree;
}
return degree == 0;
}
};
这种解法就更加巧妙了,连字符串解析都不需要了,用一个变量capacity来记录能容忍"#"的个数,跟上面解法中的degree一个作用,然后我们给preorder末尾加一个逗号,这样可以处理末尾的"#"。我们遍历preorder字符串,如果遇到了非逗号的字符,直接跳过,否则的话capacity自减1,如果此时capacity小于0了,直接返回true。此时再判断逗号前面的字符是否为"#",如果不是的话,capacity自增2。这种设计非常巧妙,如果逗号前面是"#",我们capacity自减1没问题,因为容忍了一个"#";如果前面是数字,那么先自减的1,可以看作是初始化的1被减了,然后再自增2,因为每多一个数字,可以多容忍两个"#",最后还是要判断capacity是否为0,跟上面的解法一样,我们要补齐"#"的个数,少了也是不对的,参见代码如下:
class Solution {
public:
bool isValidSerialization(string preorder) {
int capacity = 1;
preorder += ",";
for (int i = 0; i < preorder.size(); ++i) {
if (preorder[i] != ',') continue;
if (--capacity < 0) return false;
if (preorder[i - 1] != '#') capacity += 2;
}
return capacity == 0;
}
};
原文:https://www.cnblogs.com/yunlambert/p/9188764.html