反向排列句子中的词(Reverse Words in a String)

今天开始在https://oj.leetcode.com点击打开链接上刷题,好囧啊~但是还是决定开始记录刷题吧。也是大学里没做的,现在慢慢做!加油!!

题目:

Given an input string, reverse the string word by word.

For example, Given s = "the sky is blue", return "blue is sky the".

解题思路:

方案1.切分字符串获得每个词,不断将字符串逆序拼接

void reverseWords(string &str) {
        const char * str_char = str.c_str();
        int len = str.length();
        string result = "";
       for(int i = 0; i < len; )
      {
          while(i < len && str_char[i] == ' ') i++;
          if(i == len) break;
          int start = i;
          while(i < len && str_char[i] != ' ') i++;;
          string temp = str.substr(start,i-start) +" "+ result;
          result = temp;
       }
       string ss(result.substr(0,result.length()-1));
       str = ss;
    }

解析:这个方案中使用了C++的substr函数,赋值指定位置和长度的字符串,核心思想为string temp = str.substr(start,i-start) +" "+ result; result = temp;两行代码将word顺序不断逆序拼接。这种代码结构简洁,思路清晰,但是由于字符串拼接本身和substr函数本身很耗时的缘故,该方法看起来时间复杂度为O(n),实际上耗时超过该值. Run time 44 ms.

方案2 将字符串整个逆转过来,遇到空格作为一个词再次求逆

 void reverseWords(string &str) {
        int len = str.length();
        char *revers_str = new char[len+1];    //字符串逆序列

         const char* temparray = str.c_str();

         for(int i = 0 ; i < len; ++i)
        {
             revers_str[i] = temparray[ len - i -1];
        }
        revers_str[str.length()]='\0';
        int start = 0,index = 0;
        char *result = new char[len+1];
        while(start < len && revers_str[start] == ' ') start++;//去除起始的空格
        for(int i = start; i < len;)
        {
             int startindex = i; // 词的起始位置
             while(i < len && revers_str[i] != ' ') i++;
             int endindex = i -1;//词的终止位置
             for( int j = endindex; j >= startindex; j--)
                  result[index++] = revers_str[j];
   
             while(i < len && revers_str[i] == ' ' ) i++;//去除空格
             if( i < len ) result[index++]=' '; //word space
         }
         result[index]='\0';
         string ss(result);
         str = ss;
        delete revers_str, result;
    }

解析:这个方案中使用了C的c_str函数,获取字符串的字符数组,用一个循环获得逆序,之后顺序读取字符判断,获得每个词的起始终止位置,再次逆序使得词正确。这个方案虽然没有字符串拼接,但是两遍循环和字符逆序,相当于每次都要至少遍历3次字符串,耗时也很长 Run time 40ms.

方案3 改进的逆序法,使用在逆序时就记录词的位置,可以在第二次扫描时直接加入空格成为答案。

void reverseWords(string &str) {
        int len = str.length();
        char *revers_str = new char[len+1];
        int* space_indexs = new int[len+1];
        space_indexs[0] = 0;
        int word_num = 0, revers_len = 0;
        const char* temparray = str.c_str();
        for(int i = 0 ; i < len;)  //字符串求逆 并记录space位置
       {
           while(i < len && temparray[ len - i -1] == ' ') i++;
           if(i == len) break;
           while(i < len && temparray[ len - i -1] != ' ')
           {
                 revers_str[revers_len++] = temparray[ len - i -1];
                 i++;
            }
            space_indexs[word_num++] = revers_len -1;
         }
         revers_str[revers_len]='\0';
    
         int result_len = 0;
         char *result = new char[len+1];
         for(int j =space_indexs[0]; j >=0 ; j--) //记录第一个词
             result[result_len++] = revers_str[j];
    
         for(int i = 1; i < word_num; i++) //记录接下来的词,每个词前有space
        {
              result[result_len++] = ' ';
              for(int j = space_indexs[i]; j > space_indexs[i -1]; j-- )
                       result[result_len++] = revers_str[j];
        }
        result[result_len] = '\0';
        string ss(result);
        str = ss; //返回值

    }

解析:这个方案是三个方案中耗时最小的方案,通过一次遍历记录了每个词的分割位置,并将字符序列求逆。但现在想想貌似直接记录词的位置第二次逆序读取似乎可以更好。 Run time 12ms. 注意!!!我忘记delete了~

总结:

1. 关于格式,对空格要求比较多,所以输出时要格外小心。关于Output Limited,使用了引用传值,所以最后不用自己print,而是赋值回去。

2.关于RunTime Error,可能就是溢出,包括数组越界,递归栈溢出,数组下标为负,除以0等。在第三个方案中我开始忘记了对space_index[0]的初始化,直接导致后来有可能使用到为赋值的值,以后有东西了可以memset一下。开数组定义变量要想想不初始化的危险性。

3.关于new 和静态数组,我一直喜欢new,delete,结果还是忘记delete。还有就是其实静态数组在刷题和很多情况下都蛮有用的,省了很多new和delete的时间。有人提醒我说,全局的东西可以new,局部的就别再new了。

备注:由于还不会插入代码,所以代码格式是手动调的。。忍忍吧~~o(╯□╰)o

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值