題目:
定義字符串的左旋轉操作:把字符串前面的若干個字符移動到字符串的尾部。如把字符串abcdef 左旋轉2 位得到字符串cdefab。
請實現字符串左旋轉的函數,要求時間對長度爲n 的字符串操作的複雜度爲O(n),輔助內存爲O(1)。
思路一:
分析:如果不考慮時間和空間複雜度的限制,最簡單的方法莫過於把這道題看成是把字符串分成前後兩部分,通過旋轉操作把這兩個部分交換位置。於是我們可以新開闢一塊長度爲n+1 的輔助空間,把原字符串後半部分拷貝到新空間的前半部分,再把原字符串的前半部分拷貝到新空間的後半部分。不難看出,這種思路的時間複雜度是O(n),需要的輔助空間也是O(n),顯然和題目要求的不符合,因此我們要用另想其他的解法。
把字符串看成有兩段組成的,記爲XY。左旋轉相當於要把字符串XY 變成YX。我們先在字符串上定義一種翻轉的操作,就是翻轉字符串中字符的先後順序,把X 翻轉後記爲XT。顯然有(XT)T=X。我們首先對X 和Y 兩段分別進行翻轉操作,這樣就能得到XTYT。接着再對XTYT 進行翻轉操作,得到(XTYT)T=(YT)T(XT)T=YX。正好是我們期待的結果。
分析到這裏我們再回到原來的題目。我們要做的僅僅是把字符串分成兩段,第一段爲前面n個字符,其餘的字符分到第二段。再定義一個翻轉字符串的函數,按照前面的步驟翻轉三次就行了。時間複雜度和空間複雜度都合乎要求。
代碼如下:
/*-----------------------------
Copyright by yuucyf. 2011.08.15
------------------------------*/
#include "stdafx.h"
#include <assert.h>
#include <iostream>
using namespace std;
void ReverseString(char* pStart, char* pEnd)
{
assert(pStart);
assert(pEnd);
char cTemp;
while (pStart <= pEnd)
{
cTemp = *pStart;
*pStart = *pEnd;
*pEnd = cTemp;
pStart++;
pEnd--;
}
}
char *LeftRotateString(char *pStr, int n)
{
if (NULL != pStr)
{
int i32Len = static_cast<int>(strlen(pStr));
if (i32Len > 0 && i32Len > n)
{
char *pFirStart = pStr;
char *pFirEnd = pStr + n - 1;
char *pSecStart = pStr + n;
char *pSecEnd = pStr + i32Len - 1;
ReverseString(pFirStart, pFirEnd);
ReverseString(pSecStart, pSecEnd);
ReverseString(pFirStart, pSecEnd);
}
}
return pStr;
}
int _tmain(int argc, _TCHAR* argv[])
{
char aszSrcStr[] = {"abcdef"};
cout << "輸入的字符串爲:"<< aszSrcStr << " 輸出的字符串爲:";
LeftRotateString(aszSrcStr, 2);
cout << aszSrcStr << endl;
return 0;
}