LeetCode 151 翻转字符串里的单词

题目:

给定一个字符串,逐个翻转字符串中的每个单词。

 

示例 1:

输入: "the sky is blue"
输出: "blue is sky the"

示例 2:

输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:

输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

 

说明:

  • 无空格字符构成一个单词。
  • 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
  • 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

 

进阶:

请选用 C 语言的用户尝试使用 O(1) 额外空间复杂度的原地解法。

解题思路:

首先把字符串左右两边多余的空格给去掉,然后用两个指针分别从两段开始向中间扫描,将扫描到的左、右两个单词进行交换。这交换过程中注意下标的变换,因为两个单词长度不一定相等。

代码:

 1 class Solution {
 2 public:
 3     string reverseWords(string s) {
 4         string temp;
 5         int l1,l2,r1,r2;
 6         l1=0,r2=s.size()-1;
 7   // 第一步:先把字符串两边的空格给去掉
 8         while(l1 <= r2) {   //1、这里取等于 可以处理 s=" "  这种特殊情况,即输出""
 9                 if(s[l1] == ' '){
10                     s.erase(l1,1);
11                     r2--;   //2、这里是r2改变,而不是l1,l1实际不需要改变
12                 }
13                 else
14                     break;
15     
16             }
17         while(l1 < r2 ) {
18                 if(s[r2] == ' '){
19                     s.erase(r2,1);
20                     r2--;
21                 }
22                 else
23                     break;
24         }
25   // 第二步:尺取左、右两个单词长度,然后交换两个单词,不断重复这个过程
26         while(l1 < r2) 
27         {
28             temp.clear();
29             for(r1=l1; r1<r2 && s[r1+1] != ' '; ++r1);   //3、找到两个单词边界
30             for(l2=r2; l2>l1 && s[l2-1] != ' '; --l2);
31             if(r1 >= l2)       //4、若只剩一个单词,则不必处理,直接退出
32                break;
33             int len1=r1-l1+1;
34             int len2=r2-l2+1;
35             temp = s.substr(l1, len1);
36             s.erase(l1,len1);
37             l2 = l2-len1;      //5、删除左边那个单词时,应该改变l2的值,但l1不用改变
38             s.insert(l1,s.substr(l2,len2));
39             l2 = l2+len2;     //6、插入之后l1,l2都要改变,因为l1要变为插入单词的下一个位置
40             l1 = l1+len2;
41             s.erase(l2,len2);
42             s.insert(l2,temp);   //7、删除第l2位置开始的单词,再从该位置插入新单词。刚开始以为l2要减一,但其实insert(index,string)的用法是从index开始插入,而不是从index的后一个开始
43             l2--;         //8、插入单词的前一个位置
44             r2=l2;
45  // 第三步:处理字符串内部多余空格
46             int i,j;
47             if(l1 >= r2)     //9、同4
48                 break;
49             else{
50                 for(i=l1; i<r2 && s[i+1] == ' '; ++i);  //10、找出左右多余空格
51                 for(j=r2; j>l1 && s[j-1] == ' '; --j);
52                 if(i == j)    //11、若位置l1和r2之间已经没有多余的单词,并且只有一个空格,则保留这个空格并结束
53                     break;
54                 else if(i > j)  //12、若位置l1和r2之间已经没有多余的单词,但有多个空格,则删除多余的,只保留一个空格即可
55                 {
56                     s.erase(l1,i-l1);
57                     r2=r2-(i-l1);
58                     break;
59                 }               
60                                  //13、若位置l1和r2之间还有单词,则删除两边多余的空格
61                 s.erase(l1,i-l1);
62                 j=j-(i-l1);
63                 r2=r2-(i-l1);
64                 s.erase(j,r2-j);
65                 r2=j-1;
66                 l1++;
67             }
68 
69         }
70         return s;
71     }
72 };

 

上一篇:【BZOJ】1066: [SCOI2007]蜥蜴(最大流)


下一篇:霸榜GitHub必读书籍:编写高质量代码改善Java程序员的151个建议