和43题类似,也是翻转字符串,写完程序有4处Bug,最大的两个错误在于:
1、写Reserve函数时不动脑子,把end--写成了end++,导致数组越界,段错误(检查了很久都没检查出来)
2、 又一次忘记了将 指针/索引 在用完后移动:每翻转完一次,begin指向end指的空格,end需要往后错一位,不然end一直满足<str.size() 且 !=‘ ’ ,陷入外层的死循环
3、忘记写return ,这会造成段错误。(原因:待补充)
4、内层循环条件应该为:str[end]!=' ' && end<str.size() 我漏掉了后一项。如果这样会导致单一单词出现问题(原因:待补充,不应该是导致内层索引越界吗?)
前两处错误都是最后1-2分钟集中发现的,之前时间浪费在了对循环条件的纠结上:
while(str[end]!=' ' && end<str.size()){
以为end 一旦 >=str.size(),循环条件自身就会出错,其实并不会?甚至去掉这个条件都不会因为数组越界出段错误,而是只有一个单词时导致结果错误。
最开始的程序:
class Solution {
public:
string ReverseSentence(string str) {
if(str.size()<3) return str;
int begin = 0;
int end = str.size()-1;
Reverse(str, begin, end);
begin = -1;
end = 0;
while(end<str.size()){
while(str[end]!=' '){
end++;
}
Reverse(str, begin+1, end-1);
begin = end;
}
}
void Reverse(string& str, int begin, int end) {
if(str.size()<2 || begin<0 || end>str.size()-1) return;
while(begin<end){
char tmp = str[begin];
str[begin] = str[end];
str[end] = tmp;
begin++; end++;
}
}
};
错误定位Bug之后的修改:
string ReverseSentence(string str) {
if(str.size()<3) return str;
int begin = 0;
int end = str.size()-1;
Reverse(str, begin, end);
begin = -1;
end = 0;
while(end<str.size()){
while(str[end]!=' ' && end<str.size()){
if(end<str.size()-1) end++;
if(end==str.size()-1) end++; break;
}
Reverse(str, begin+1, end-1);
begin = end;
}
}
最终版本程序:
class Solution {
public:
string ReverseSentence(string str) {
if(str.size()<3) return str;
int begin = 0;
int end = str.size()-1;
Reverse(str, begin, end);
begin = -1;
end = 0;
while(end<str.size())
{
while(str[end]!=' '){
end++;
if(end==str.size()-1)
{
end++;
break;
}
}
Reverse(str, begin+1, end-1);
begin = end;
end++; //这里一开始也忘记了在翻转完成后,将end移动到下一段的段首,总是忘记移动指针/索引
}
return str;
}
void Reverse(string& str, int begin, int end) {
if(str.size()<2 || begin<0 || end>str.size()-1) return;
while(begin<end){
char tmp = str[begin];
str[begin] = str[end];
str[end] = tmp;
begin++; end--; //这里不细心,写程序时不思考,导致写成end++,造成段错误
}
}
};
循环部分可以写的更简单一些:
begin = -1;
end = 0;
while(end<str.size())
{
while(str[end]!=' ' && end<str.size()){
end++;
}
Reverse(str, begin+1, end-1);
begin = end;
end++;
}
return str;
按照书上写法,改成如下:
begin = end = 0;
while(begin<str.size())
{
if(str[begin]==' '){
begin++;
end++;
}
else if(str[end]==' ' || str[end]=='\0'){
Reverse(str,begin,end-1);
begin = end;
}
else{
end++;
}
}
一开始我认为,begin < str.size() 还是 end<str.size() 都是一样的,因为我认为循环肯定是在第二个分支那里结束,但是如果
end<str.size(),那么最后一段字母序列,在 end 还没有到达 str[str.size()] 时就结束循环了,最后一段不会发生第二次翻转。
所以之前自己写的程序出错的原因也找到了:和此处一样,改成 begin< 或者 end<= (会越界)