题目描述
一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0 A1 ⋯ AN−1 )变换为(AN−M ⋯ AN−1 A0 A1 ⋯ AN−M−1 )(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:
每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。
输出格式:
在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
6 2
1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
思路
对于这个题目,虽然看似给出了很多限制,但实际上却只测试循环右移之后得到的结果而不管过程。对于这种题目,考生其实可以不用管题目中那些限制,直接输出答案即可。
首先需要注意题目并没有给定M的最大值,因此不能直接认为 M < N,而需要在读入 N 和 M 后令 M = M % N ,这样就可以保证 M < N ,使后面的操作更简便。这样做的依据是:对一个长度为 N 的序列,右移 N 位之后的序列和当前序列是相同的。
在得到新的 M 后,可以直接输出序列从 N - M 号元素到 N - 1 号元素,再输出 0 号元素到 N - M - 1 号元素即可。
注意点
① 处理最后一个数字之后不输出空格可以使用 count 变量记录已经输出数的个数,只要 count 没有达到 N ,就输出空格。
② 由于 M 有可能为 0 ,因此可以直接输出整个数组。某些写法如果没有考虑这种情况,则会导致两组数据 “运行超时” 。
③ 同样要注意最后一个数后不能输出空格,否则会返回 “格式错误” 。
代码:
#include <stdio.h>
int main() {
int a[110];
int n, m, count = 0; // count 记录已经输出数的个数
scanf("%d%d", &n, &m);
m = m % n; // 修正 m
for(int i=0; i<n; i++) {
scanf("%d", &a[i]);
}
for(int i=n-m; i<n; i++) { // 输出 n-m 号到 n-1 号
printf("%d", a[i]);
count++; // 已输出数的个数加 1
if(count < n) printf(" "); // 如果已经输出数的个数小于 n ,则输出空格
}
for(int i=0; i<n-m; i++) { // 输出 0 号到 n-m-1 号
printf("%d", a[i]);
count++;
if(count < n) {
printf(" ");
}
}
return 0;
}
结果: