leetcode-151-翻转字符串里的单词

题目描述:

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

示例:  

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

说明:

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

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

要完成的函数:

void reverseWords(string &s) 

说明:

1、这道题给定一个字符串s,相当于一个英文句子,要求把这个句子中的单词反转一下,后面的要放在前面,前面放在后面。

这个句子中可能会有多余的空格,可能会出现在第一个字符前面,可能出现在单词之间,可能出现在最后一个字符后面。

你要将多余的空格去掉,最前面和最后面不能有空格,单词之间的空格只能有一个。

c或c++语言用户使用O(1)空间复杂度的原地解法,在字符串中修改,函数类型是void,不用返回。

2、这道题如果允许多定义一个新字符串(长度与给定字符串相同),那么从给定字符串的后面读起,读出的字符从新的字符串的前面开始写起。

在写的过程中,调整新字符串的空格,使之符合要求,最后调用resize函数修改新字符串的长度,这道题也就解决了。

但现在要求原地解法,那么只能逐个交换了,后面跟前面交换,这样子换完之后,单词内部顺序也是反过来的,那再在单词内部交换一下,也就ok了。

至于多余的空格问题,可以在交换之前,先解决掉这个问题,把后面的字符往前面移。

笔者的代码思路如下,举个例子,字符串是   "(两个空格)the(三个空格)sky(两个空格)is(一个空格)blue(两个空格)":

1、先反转整个字符串,变成(两个空格)eulb(一个空格)si(两个空格)yks(三个空格)eht(两个空格)。

2、把后面的字符往前挪,去掉多余的空格,变成eulb(一个空格)si(一个空格)yks(一个空格)eht

3、在单词内部进行反转,变成blue(一个空格)is(一个空格)sky(一个空格)the。

所以具体代码如下:(附详解)

    void reverseWords(string &s) 
    {
        reverse(s.begin(),s.end());//先进行整个字符串的反转
        int i=0,j=0,start=0,t;
        while(i<s.size())//把字符往前挪,去掉多余的空格
        {
            while(i<s.size())//找到第一个非空格字符
            {
                if(s[i]!=' ')
                    break;
                i++;
            }
            if(i==s.size())break;//如果找不到非空格字符,此时已经i==s.size(),所以直接结束这一部分的任务
            j=i+1;
            while(j<=s.size())//找到i后面的第一个空格字符,位置记为j
            {
                if(s[j]==' '||s[j]=='\0')
                    break;
                j++;
            }
            while(i<j)//把i和j之间的字符往前挪,第一个就搬动到start这个位置,第二个搬动到start+1这个位置……
            {
                s[start]=s[i];
                start++;
                i++;
            }
            s[start]=' ';//搬完一个单词之后,start现在这个位置变成空格字符
            start++;//start到空格的下一位,作为新的单词的起点
            i++;//i退出循环时,i==j,现在i++,变成空格的下一位,继续找下一个单词的起点
        }
        if(start==0)//边界条件,如果结束了上述任务之后,start还是为0,说明根本就没有非空格字符,那么s变成空字符串
			s=s.substr(0,0);
		else
		{
			s=s.substr(0,start-1);//去掉字符串后面多余的长度
	        i=0,j=1;
	        while(i<s.size())//把每一个单词反转过来
	        {
	        	while(j<=s.size())//找到空格位置,记为j
		        {
		        	if(s[j]==' '||s[j]=='\0')
		        		break;
		        	j++;
				}
				t=j+1;//记下来,作为下一个单词的起始位置
				j--;
				while(i<j)//单词内部反转
				{
					swap(s[i],s[j]);
					i++;
					j--;	
				}
				i=t,j=i+1;//更新i和j的位置
			}   
		}
        	

上述代码实测4ms,beats 98.93% of cpp submissions。

猜你喜欢

转载自www.cnblogs.com/king-3/p/9613213.html
今日推荐