1. 程式人生 > >演算法練習:一維陣列旋轉

演算法練習:一維陣列旋轉

題目描述:求一個一維陣列向右旋轉K個位置後的結果。比如,一維陣列{1, 2, 3, 4, 5},當k = 2時,求得的結果為{4, 5, 1, 2, 3}。要求常數級空間複雜度,允許修改原有陣列。

一、使用額外的空間(在不要求常數級空間複雜度的情況下)

這樣很簡單,使用一個額外的空間,儲存原有陣列的元素,然後可以錯位複製原有陣列

元素,即可達到題目的要求。比如陣列{1, 2, 3, 4, 5},當k = 2時,先將45複製到結果陣列,然後將123複製到結果陣列的後面部分。

//使用額外空間進行陣列旋轉
void RotateArrayK_Ext( int nArray[], int nCount, int k )
{
	if ( nArray == NULL || nCount <= 0 || k < 0 || k > nCount ) return;

	int* pArrayTemp = new int[nCount];
	if ( NULL == pArrayTemp ) return;

	//備份資料
	for ( int i = 0; i < nCount; ++i )
	{
		pArrayTemp[i] = nArray[i];
	}

	//進行錯位複製
	int i = 0;
	for ( i = 0; i < k; ++i )
	{
		nArray[i] = pArrayTemp[nCount-k+i];
	}

	for ( int j = 0; i < nCount; ++i )
	{
		nArray[i] = pArrayTemp[j++];
	}
}

函式RotateArrayK_Ext的空間複雜度為O(n),時間複雜度也為O(n),顯然,在空間複雜度這一塊是不符合題目要求的。

二、常數級空間複雜度且允許修改原有陣列

在此要求下,我們可以對陣列進行三次反轉,從而求得結果。三次反轉陣列:第一次反轉整個陣列;第二次反轉陣列前K個數;第三次反轉剩下的數。例如:

一維陣列{1, 2, 3, 4, 5}k = 2

第一次反轉:54321

第二次反轉:45321

第三次反轉:45123

程式程式碼如下:

//反轉陣列
bool ReverseArray( int nArray[], int nCount, int nStart, int nEnd )
{
	if ( nArray == NULL || nCount <= 0 ) return false;
	if ( nStart < 0 || nStart >= nCount ) return false;
	if ( nEnd < 0 || nEnd >= nCount ) return false;


	while( nStart < nEnd )
	{
		int nTemp = nArray[nStart];
		nArray[nStart] = nArray[nEnd];
		nArray[nEnd] = nTemp;

		++nStart;
		--nEnd;
	}

	return true;
}


//對陣列實施三次反轉來進行陣列的旋轉
void RotateArrayK( int nArray[], int nCount, int k )
{
	if ( nArray == NULL || nCount <= 0 || k < 0 || k > nCount ) return;

	//反轉整個陣列
	ReverseArray( nArray, nCount, 0, nCount - 1 );

	//反轉前K個數
	ReverseArray( nArray, nCount, 0, k - 1 );

	//反轉剩下的數
	ReverseArray( nArray, nCount, k, nCount - 1 );


}


此演算法擁有常數級的空間複雜度,因為演算法裡執行了三次反轉陣列,反轉陣列都是線上性時間裡完成的,所以此演算法的時間複雜度為O(n)

系列文章說明:
1.本系列文章[演算法練習],僅僅是本人學習過程的一個記錄以及自我激勵,沒有什麼說教的意思。如果能給讀者帶來些許知識及感悟,那是我的榮幸。
2.本系列文章是本人學習陳東鋒老師《進軍矽谷,程式設計師面試揭祕》一書而寫的一些心得體會,文章大多數觀點均來自此書,特此說明!
3.文章之中,難免有諸多的錯誤與不足,歡迎讀者批評指正,謝謝.

作者:山丘兒
轉載請標明出處,謝謝。原文地址:http://blog.csdn.net/s634772208/article/details/46417297