一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0A1⋯A**N−1)变换为(A**N−M⋯A**N−1A0A1⋯A**N−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
代码:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
int [] arr=new int[n];
for (int i = 0; i <arr.length ; i++) {
arr[i]=sc.nextInt();
}
//将m转为0到n间的右移位数,方便下面计算
int num=m%n;
//如果右移位数为0,则直接输出原数组即可,不为零执行下面的操作
if(num!=0){
//x 为第一个右移的下标
int x=0;
//判断是数组长度是否为右移位数的倍数,若为倍数则需要双重循环,反之则只需一层循环
if (n%num==0){
for (int i = 0; i <num ; i++) {
//x 为第一个右移的数的下标
x=i;
//replace 为第一个右移的数的值
int replace=arr[x];
//next 为第一个右移的数应移到的下标
int next= (num+x)%n;
for (int j = 0; j < n/num; j++) {
//pre 为应右移到下标为x的下标
int pre= (x+n-num)%n;
//将应右移到下标为x的数赋值给arr[x]
arr[x]=arr[pre];
//x设为上一个赋值给arr[x]的下标
x=pre;
}
//将第一个右移的值赋给下标为next的arr值
arr[next]=replace;
}
}else {
int replace=arr[x];
int next= (num+x)%n;
for (int i = 0; i <arr.length ; i++) {
int pre= (x+n-num)%n;
arr[x]=arr[pre];
x=pre;
}
arr[next]=replace;
}
}
for (int i = 0; i < arr.length; i++) {
if (i==0){
System.out.print(arr[i]);
}else {
System.out.print(" "+arr[i]);
}
}
}
}
思路:
1.因为题目中不能使用其他数组,而且要使移动数据的次数尽量少,所以有点麻烦
2.我画个图,让你们稍微容易理解一点吧
3.ps:我这是属于倒叙插入右移,也可以正序插入右移,应该比我这个好理解一点。
正序插入右移:
以第一次外层循环举例:
可以先将 数值为3的值和下标保存,然后执行④将1的值插入,
然后保存数值为5的值和下标,然后执行③,将3的值插入,循环往复。
注意:
1.当m为0,或者m右移位数num为0的时候,需单独考虑!