问题描述
给定一个n长的数列,有m次操作,第i次操作表示将整个数列循环移动mi位,询问每次操作结束后的开头k个数字
输入格式
第一行三个整数n,m,k。
第二行n个整数表示数列。
接下来m行,每行一个整数mi,表示移动位数,若mi为正,表示向左移mi位,若mi为负数,表示向右移-mi位。
输出格式
m行,每行k个数,表示开头k个数字
样例输入
5 2 3
1 2 3 4 5
2
-2
样例输出
3 4 5
1 2 3
数据规模和约定
n<=1000000
m<=100000
k<=min(10,n)
mi<=100000000
思路:若是直接移动数组,对时间和空间的开销比较大,因为肯定要创建新数组来存储移动后的数据,这样是很不理想的,所以我们可以换一个思维,我们想象一个开始的索引,直接在原数组上移动索引,把这个索引的位置看作数组开头的位置,输出索引及其后面k个位置的数字就行。
但是又有两个问题,移动的距离加上原来的索引大于数组长度怎么办,该怎么移动,若索引加上移动的距离小于0,又怎么办?
这里不管左移动还是右移动,我们都让索引加上移动的距离,若是小于0,我们让它加n,直到大于0,若是大于n,则让他对n取模,因为不管左移还是右移,移动n位都相当于不移动,即移动n位肯定会回到原状态。
控制移动的代码:
private static void act(int p){ // 移动的方法
index += p; // 移动后的索引位置
while (index<0)
index += n; // 索引不能为负
for (int i=0;i<k;i++){
System.out.print(nums[(i+index)%n]+" "); // 就从索引开始,往后共输出k个数
}
System.out.println(); // 控制输出格式
}
p是当前传入的整数,例如若是-2,则是向右移2位,即开始索引变为(0-2+n)% n,即n-2。index是全局变量,初值为0。
然后呢,还需要注意一个问题,就是本题的数据规模很大,若是用Scanner,会超时,所以我们要用BufferedReader来读取输入流,本题我用BufferedReader才勉强通过100分。要真让我说BufferedReader和Scanner的区别我是真说不清楚,只有说在对于大规模数据处理的时候,BufferedReader的效率更高,若数据规模小,两者选择谁都没有影响。大家想深入了解它俩的区别的话,可以自行百度看看。
完整代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class 移动 {
static int n,m,k; // 定义n,m,k为全局变量,方便访问
static int[] nums = new int[1000020]; // 数字数组
static int[] orders = new int[100020]; // 执行移动命令的数组
static int index = 0; // 初始数组的开始位置,用移动开头索引的方式来替代移动数组,提高效率
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String[] s = reader.readLine().trim().split(" "); // 存放n,m,k的值的数组
n=Integer.parseInt(s[0]); // 给n,m,k赋值(转化为整型)
m=Integer.parseInt(s[1]);
k=Integer.parseInt(s[2]);
String[] s2 = reader.readLine().trim().split(" "); // 获取数组中的各个数
for (int i=0;i<n;i++)
nums[i] = Integer.parseInt(s2[i]); // 转化为整型
for (int i=0;i<m;i++)
orders[i] = Integer.parseInt(reader.readLine().trim()); // 接收移动的命令
reader.close(); // 关闭输入流
for (int i=0;i<m;i++)
act(orders[i]); // 执行移动
}
private static void act(int p){ // 移动的方法
index += p; // 移动后的索引位置
while (index<0)
index += n; // 索引不能为负
for (int i=0;i<k;i++){
System.out.print(nums[(i+index)%n]+" "); // 就从索引开始,往后共输出k个数
}
System.out.println(); // 控制输出格式
}
}
蓝桥杯AC结果: