151. Reverse Words in a String
仅供自己学习
思路:
可以使用原地算法进行反转,首先我们将整个string反转,然后对每个单词进行单独的反转,那么这里有个问题就是,如何解决多余的空格,让string只有在相邻两个单词之间才会有空格。
如图所示。
首先我们需要一个变量idx来作为指导赋值的索引指针。然后对原string进行遍历,首先判断遍历到的元素是不是空格,如果是就跳过,如果不是那么就是找到了一个单词,接着就判断idx是否为0,这个判断在后面解释,然后定义一个end=start用于找到这个单词的末尾,start指向这个单词的开头,然后while循环,end右移,判断是否小于string的长度并且end遍历到的元素不为空格,那么就对idx所在的位置赋值end所在的位置得元素,并且两个指针都右移。该循环结束后,reverse这个单词,这个单词开始的地方就是s.begin()+idx-(end-start),(开始的地方不是s.begin()+start是因为我们反转的是重新复制后的这个单词的位置,)结束位置为s.begin()+idx,再将start=end,说明开始寻找新的单词。当找到下一个单词的时候 idx不为0,但是idx仍然在上一个单词的最后一个字母的后面一个位置,那么就给这个位置赋值为‘ ’,那么每个单词之间就只有一个空格了。在遍历结束后最后我们还要特别去除s.begin()+idx到s.end()的元素,因为此时可能有的例子前面有多个空格,到最后的单词重新赋值后,后面还有这个单词的一些字母和空格,所以要去掉。
代码:
1 class Solution { 2 public: 3 string reverseWords(string s) { 4 reverse(s.begin(),s.end()); 5 int idx=0; 6 int n=s.length(); 7 for(int start=0;start<n;++start){ 8 if(s[start]!=' '){ 9 if(idx!=0) s[idx++]=' '; 10 int end=start; 11 while(end<n && s[end]!=' ') s[idx++]=s[end++]; 12 reverse(s.begin()+idx-(end-start),s.begin()+idx); 13 start=end; 14 } 15 } 16 s.erase(s.begin()+idx,s.end()); 17 return s; 18 } 19 };
另一种是通过双端队列,我每次从前面把单词加入,取出的时候是从前面取,那么就可以做到反转了。
首先是去掉开头的空格和末尾的空格,用一个char 变量c来存储遍历到的s的每个元素,只要是非空格的元素就合并到string word这个变量去存储单词,当遇到空格后就将word从队列前端放入,并将word清空,然后再次循环,直到遍历结束,因为我们用while循环,条件是left<=right,那么最后一个单词我们是没有加入进去的,所以在循环结束后要单独加入进队列中。然后就用一个string res每次都从队列将的单词取出来,然后判断是否队列为空,不为空就加一个空格。
代码:
1 class Solution { 2 public: 3 string reverseWords(string s) { 4 int n=s.size(); 5 deque<string> q; 6 string word=""; 7 int left=0,right=n-1; 8 while(left<=right&&s[left]==' ') left++; 9 while(left<=right&&s[right]==' ') right--; 10 11 while(left<=right){ 12 char c = s[left++]; 13 if(word.size()&&c==' '){ 14 q.push_front(word); 15 word=""; 16 } 17 else if(c!=' ') { 18 word+=c; 19 } 20 } 21 q.push_front(word); 22 string res; 23 while(!q.empty()){ 24 res += q.front(); 25 q.pop_front(); 26 if(!q.empty()) res+=" "; 27 } 28 return res; 29 } 30 };