00-自測3. 數組元素循環右移問題 (20)
一個數組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
分析每個數據與目標位置之間的下標關係,將每個數據一次性定位。
#include<iostream>
using namespace std;
#define Swap(a,b) a^=b,b^=a,a^=b; //連續3次異或運算交換a與b
int gcd(int a,int b){ //gcd算法求最大公約數
return a==0 ? b : gcd(b%a,a);
}
int main()
{
int i,j=0,N,M,temp,flag;
int c[100];
cin>>N>>M;
for(i=0;i<N;i++){
cin>>c[i];
}
if(M>N) M = M % N; //M>N的處理
int t=gcd(N,M); //移動環的個數
for(i=0;i<t;i++){
temp=c[i];
int k=i;
flag=(i-M+N)%N; //將要移到第i位置的數據位置
if(flag==i) //M爲N的整數倍時,不用移動
break;
int n=0,m=0; //while循環的跳出標誌
while(!n){
Swap(c[k],c[flag]);
if(m==1)
n=1;
else{
k=flag;
flag=(k-M+N)%N;
if(flag==(i+M)%N) //檢測第i位置數據將移入的位置時再進行一次交換
m++;
}
}
c[flag]=temp;
}
for(i=0;i<N-1;i++)
cout<<c[i]<<" ";
cout<<c[i]<<endl;
return 0;
}