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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章