算法练习:一维数组旋转

题目描述:求一个一维数组向右旋转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


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值