自测3. 数组元素循环右移问题

一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0A1……AN-1)变换为(AN-M …… AN-1 A0 A1……AN-M-1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:每个输入包含一个测试用例,第1行输入N ( 1<=N<=100)、M(M>=0);第2行输入N个整数,之间用空格分隔。

输出格式:在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

输入样例:
6 2
1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
题目链接:http://www.patest.cn/contests/mooc-ds2015spring/00-%E8%87%AA%E6%B5%8B3
刚开始花了不少时间在想,用一种比较简单的方法解决,下面同时把几种网友的方法也做一下简单汇总。
下面是一种很简单易懂的方式,利用数组多余的空间进行替换。
方法一:扩大数组空间,根据相应规则将前N个数值重新组合
分析:时间: O(1);空间:O(2*n)。
<pre name="code" class="cpp">	void m::move_k1(int *a,int n,int k)
	{
		int i;
		//当M<=N-M时,先把最后M个数值放置在前M个,剩余的再重排 
		if(k<=n-k)
		{
			for(i=0;i<k;i++) 
				a[i]=a[2*n-(k-i)];
				
			for(i=k;i<n;i++) 
				a[i]=a[n-k+i];
		}
		//当M>N-M时,先把前面N-M个数值放置在后N-M个,剩余的再重排 
		else
		{
			for(i=k;i<n;i++) 
				a[i]=a[i-k+n];
	
			for(i=0;i<k;i++) 
				a[i]=a[2*n-k+i];
		} 
	}
 
方法二:每次移动一个元素,移动k次。
分析:时间: O(n * k);空间:O(1)。
 
<pre name="code" class="cpp">	//向右循环移动 
 	void m::move_k1(int *a,int n,int k)
	{
	    int i;
	    for(i=0;i<k;i++)	//向右移k次 
	    {
	        int temp;
	        int j=-1;
	        temp=a[n-1];
	        for(j=n-1;j>0;j--)	//每次向右移一位 
	            a[j]=a[j-1];
	        a[0]=temp;
	    }
	}

 方法三:通过三次倒置运算,得到最终结果 

分析:时间: O(n);空间:O(1)。

<pre name="code" class="cpp">	m1.reverse(a,0,n-1);//将所有元素逆置;
	m1.reverse(a,0,k-1);//将前k个元素逆置;
	m1.reverse(a,k,n-1);//将后 n-k个元素逆置;
		
 	void m::reverse(int *a,int p,int q)
	{
 		int i;
   	·  for(i=p;i<=(p+q)/2;i++)	
    	{
	   		int temp;
			temp=a[i];
			a[i]=a[p+q-i];
			a[p+q-i]=temp; 
   		}
	}


 

还有通过最大公约数欧几里得算法求解的,有兴趣可以继续搜索。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值