# include <iostream>
# include <algorithm>
using namespace std;
void showarr(int * a, int N)
{
for(int i=0;i<N;++i){
printf("%d", a[i]);
if(i != N-1){
printf(" ");
}
}cout << endl;
}
int gcd(int a, int b)
{
return b==0 ? a : gcd(b, a%b) ;
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);
int a[n];
for(int i=0;i<n;++i)
scanf("%d", &a[i]);
m = m % n;
// 先反转前面N-M个元素,然后反转后M个元素,最后反转整个数组(记住分界点是要移动的第一个元素的索引n-m)
// reverse(a, a + n-m);
// reverse(a + n-m , a + n);
// reverse(a, a + n);
// 移动次数最少的方法,从要移动的元素开始(如m=2,就要从123456的5开始),将应该在当前位的元素3移动到当前位5,
// 并继续将应在当前位的元素它原本位置的应在那的元素1继续移动到3,直到下一次要移动的元素位置是最初的5,就将5复制到现在位置(1的位置),然后开始6
if(m == 0){
showarr(a, n);
return 0;
}
int pos, next, temp;
int d = gcd(m, n);
for(int i = n-m; i < n-m + d ;++i)
{ // 从n-m开始就是要移动的元素,原本是一直遍历到数组最后的,但是会出问题,所以取最大公约数
temp = a[i]; // 拿走当前位置的元素,以空出来移动元素
pos = i; // 记录当前要处理的位置
do{
// 计算应该在pos上的元素的当前位置
next = (pos - m + n) % n;
// 如果下个位置不是初始点就将应该当前位置的元素移动过来,如果下个位置是初始点就把存储的元素赋值到当前位置
a[pos] = (next != i ? a[next] : temp);
pos = next; // 前往刚被移动而空出的元素的位置
}while(pos != i); // 循环直到回到初始位置i
}
showarr(a, n);
return 0;
}
/*
int main(void)
{
int N, M;
scanf("%d %d", &N, &M);
int a[N];
for(int i=0;i<N;++i)
scanf("%d", &a[i]);
// showarr(a, N);
M = M % N;
int i = 0;
int circle = N-M;
while(i < circle && i < N && circle < N)
{
swap(a[i++], a[circle++]);
if(circle >= N)
circle = N-M;
}
showarr(a, N);
return 0;
}
*/
【PAT乙级、C++】1008 数组元素循环右移问题 (20分)
最新推荐文章于 2021-03-15 15:23:51 发布