每天學習一算法系列(24)(實現字符串左旋轉的函數)

題目:
定義字符串的左旋轉操作:把字符串前面的若干個字符移動到字符串的尾部。如把字符串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;
}


 

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