陣列迴圈移位

九茶發表於2014-11-16

問題描述:

對於一個含有n個元素的陣列a,將它的所有元素向後移動k位。


解決方案:

1最笨最直接的方法,就是把陣列移動k次,每一次都把陣列的所有元素向後移動一位,時間複雜度為O(k*n)。具體程式碼如下:
void First_kind(int a[],int n,int k)
{
	k%=n;
	while(k--)///////////////移動k次,每次都將所有元素向後移動一位。
	{
		int t=a[n-1];
		for(int i=n-1;i>0;i--)
			a[i]=a[i-1];
		a[0]=t;
	}
}


2、可以用空間換時間的思想對方法1進行優化,即另外開闢一個一樣大的陣列b,把a移位複製到b,再逐個把元素賦值到a。時間複雜度為O(n)。具體程式碼如下:
void Second_kind(int a[],int n,int k)
{
	int b[256];
	for(int i=0;i<n;i++)
		b[i]=a[(i-k+n)%n];/////////////////////將陣列a的元素移位後賦給b
	for(i=0;i<n;i++)
		a[i]=b[i];
}


3、對方法1進行更進一步的優化,我們可以只移動一次,將每個元素一次向後移動k位,時間複雜度為O(n)。
例如a={1,2,3,4,5,6,7,8},n=8,要向後移k=3位。則先令t=a[0],然後a[0]=a[(0-3+8)%8]=a[4],a[4]=[(4-                3+8)%8]=a[1],,,即a[i]=a[(i-k+n)%n]。
注意:當k=4時,t=a[0],a[0]=a[4],a[4]=t。此時如果還是i=(i-k+n)%n的話將產生重複移位。此時應該令i=j+1(j為      移位的起始位置)開始繼續移位,即t=a[1],a[1]=a[5],a[5]=t。。。。。
具體程式碼如下:
void Third_kind(int a[],int n,int k)
{
	int i,j,t,m;////////////////////////////t用來存放起始的元素值,j用來存放起始的位置,m用來記錄移動的元素數,當m==n時表示移動完成。
	k%=n;
	for(m=i=j=0,t=a[i];m<n;m++)
	{
		if((i-k+n)%n==j)///////////////////如果i的下一個結點是j,但j元素已經移動過了的,值在t裡面,則令a[i]=t,i從j+1的位置繼續移動。
		{
			a[i]=t;
			i=++j;
			t=a[i];
			continue;
		}
		a[i]=a[(i-k+n)%n];
		i=(i-k+n)%n;
	}
}


4、這種方法算是通過取巧的方法,比較少人會想到。時間複雜度也是O(n)。
例如a={1,2,3,4,5,6,7,8},n=8,要向後移k=3位。我們可以按如下步驟移:
   a、將陣列分成兩段,"1,2,3,4,5" 和 "6,7,8"
   b、把這兩段分別逆序,則a陣列變成"5,4,3,2,1,8,7,6"
   c、把陣列a整段逆序,則a變成了"6,7,8,1,2,3,4,5",這不就是我們要的答案了嗎!
具體程式碼如下:
void Change(int *a,int i,int j)//////////////////////////函式Change實現陣列a從i元素到j元素逆序。
{
	for(;i<j;i++,j--)
	{
		int t=a[i];
		a[i]=a[j];
		a[j]=t;
	}
}

void Fourth_kind(int *a,int n,int k)
{
	Change(a,0,n-k-1);
	Change(a,n-k,n-1);
	Change(a,0,n-1);
}



轉載請註明出處,謝謝!(原文連結:http://blog.csdn.net/bone_ace/article/details/41173393

相關文章