输入格式:每个输入包含一个测试用例,第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
本题要求不能使用新的数组,要做出优秀的算法不太简单。。。
循环右移n个元素,那么复杂度最小应该可以做到O(N)
那么可以先求出M和N的最大公约数gcd
gcd为多少,移动的元素就构成了多少个circle。按上面的例子,6,2的gcd是2,数组中的元素其实是分成了两组来移动的,1,3,5一组,2,4,6一组
我们就可以按照这个方法来设计移动的方法了。
最后写出来的程序,时间O(N),空间O(1),每一个circlr只需移动 n/gcd+1次元素。移动次数不可能比这个更低了
贴代码
#include <stdio.h> #include <stdlib.h> int n,m,*a; int gcd(int a,int b) { if(a%b==0){ return b; } return gcd(b,a-a/b*b); } int main(void) { scanf("%d%d",&n,&m); m=m%n; a=(int *)malloc(n*sizeof(int)); for(int i=0;i<n;i++){ scanf("%d",&a[i]); } int time=gcd(m,n); int temp,j; for(int i=0;i<time;i++){ temp = a[i]; j=i; while(1){ a[j]=a[(j+n-m)%n]; j=(j+n-m)%n; if(j==(i+m)%n){ a[j]=temp; break; } } } printf("%d",a[0]); for(int i=1;i<n;i++){ printf(" %d",a[i]); } }
时间: 2024-11-06 13:22:22