剑指Offer:44翻转单词顺序(翻转字符串)

和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<= (会越界)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值