天天看點

左旋轉字元串 left rotate string左旋轉字元串

左旋轉字元串

題目:字元串的左旋轉操作:把字元串前面的若幹字元移到字元串的後面。例如:字元串abcdefg左旋轉2位得到cdefgab。請實作左旋轉字元串函數,要求對于長度為n的字元串,時間複雜度為O(n),輔助記憶體為O(1)。

算法思想: 可以利用三次字元串反轉操作,來達到左旋轉字元串的目的: 1.反轉字元串的前半段; 2.反轉字元串的後半段; 3.反轉整個字元串。

代碼如下:

#include<iostream>
#include<string.h>

using namespace std;

// 本函數對string的子串進行反轉操作
// start和end分别指明了字串的起始位置和結束位置(左閉右開區間)
void revert_string(char* string, int start, int end)
{
	int i=start, j=end-1;
	char tmp;
	while(i<j)
	{
		tmp = *(string+i);
		*(string+i) = *(string+j);
		*(string+j) = tmp;
		i++;
		j--;
	}

}

// 進行三次反轉操作就可以完成左字元串旋轉操作
void leftRotateString(char* string,  int i)
{
	int len = strlen(string);
	revert_string(string,0,i);
	revert_string(string,i,len);
	revert_string(string,0,len);
}

int main(){
	// declaring string as a char pointer instead of a char array
	// will cause the program to crash, i.e., using the following declaration
	//        char* string = "This_is_a_sample_string";
	// will make the program crash
	char string[] = "This_is_a_sample_string";
	leftRotateString(string, 4);
	cout<<string<<endl;
	return 0;
}
           

輸出如下:

“_is_a_sample_stringThis”

除了上面的算法,還有一個著名的雜技算法。移動S[0]到臨時變量t,然後移動S[K]到S[0];移動S[2K]到S[K],依此類推(将S中的所有下标對n取模),直到傳回到取S[0]中的元素,此時改為從t取值然終止過程。當n為12,k為3時,元素按如下順序移動(如下圖,畫得太醜了,莫怪)。如果該過程沒有移動全部的元素,則從S[1]開始再次移動,直到所有的元素都已經移動位置。 代碼如下:

#include<iostream>
 #include<string>
 using namespace std;
 
 //求兩個整數i,j的最大公約數
 int gcd(int i,int j)
 {
     while(i != j)
     {
         if(i > j)
             i -= j;
         else
             j -= i;
     }
     return i;
 }
 
 
 //左旋轉字元串函數,将pStr字元串向左旋轉k位,
 //first指向pStr[i],second指向pStr[2i],以此類推
 char* LeftRotateString(char* pStr,int k)
 {
     if(pStr == NULL || k < 1)
         return 0;
 
     int n = strlen(pStr);
     
     //共進行i趟循環,i為n,k的最大公約數
     for(int i = 0;i < gcd(n,k);++i)
     {
         char temp = pStr[i];
         int first = i;
         while(1)
         {
             int second = (first + k) % n;
 
             if(second == i)
                 break;
             
             pStr[first] = pStr[second];
             first = second;
         }
 
         //将臨時變量中的字元存至每一趟的循環的最後一個字元中
         pStr[first] = temp;
     }
     return pStr;
 }
  
 int main()
 {
     string demo("abcdefgh");
     cout<<demo<<endl;
 
     LeftRotateString(&demo[0],3);
 
     cout<<demo<<endl;
     return 0;
 }