专栏:PAT乙级刷题笔记
题目
一个数组 A A A中有 N N N个整数,不使用额外空间,将整个数组循环右移 M M M位
输入格式
每个输入包含一个测试用例,第1行输入 N ( 1 ≤ N ≤ 100 ) N(1\leq N\leq 100) N(1≤N≤100)和 M ( ≥ 0 ) M(\geq 0) M(≥0);第2行输入整个 N N N个整数,之间用空格分隔。
输出格式
输出循环右移后的序列,用空格分隔。
输入样例
6 2
1 2 3 4 5 6
输出样例
5 6 1 2 3 4
分析
经典问题了。对一个数组
a
1
,
a
2
,
.
.
.
,
a
n
a_1,a_2,...,a_n
a1,a2,...,an循环右移
m
m
m位可以用如下的办法(不使用额外空间)
将前
n
−
m
n-m
n−m个数、后
m
m
m个数分别逆置(逆置算法很简单),即变成:
a
n
−
m
,
a
n
−
m
−
1
,
.
.
.
,
a
1
,
a
n
,
.
.
.
,
a
n
−
m
+
1
a_{n-m},a_{n-m-1},...,a_1,a_n,...,a_{n-m+1}
an−m,an−m−1,...,a1,an,...,an−m+1再对整个数组进行逆置就好了:
a
n
−
m
+
1
,
.
.
.
a
n
,
a
1
,
.
.
.
,
a
n
−
m
a_{n-m+1},...a_n,a_1,...,a_{n-m}
an−m+1,...an,a1,...,an−m
然而写代码的时候发现根本不需要这样,直接在输入数据的时候动手脚,输入前
n
−
m
n-m
n−m个数据时,放到后
n
−
m
n-m
n−m个位置上,输入后面的数据就放到前面的位置上。
写完了发现只是部分正确,问题出在
m
m
m上,这里并没有规定
m
≤
n
m\leq n
m≤n,所以
m
m
m还要对
n
n
n取余
代码
#include<iostream>
#include<string>
using namespace std;
int main(){
int n,m,t;
cin>>n>>m;
m = m%n;//取余
int *A = new int[n];
for(int i = 0;i < n;++i){
cin>>t;//用t存放输入的数据
if(i < n-m)
A[i+m] = t;
else
A[i-(n-m)] = t;
}
for(int i = 0;i < n-1;++i)
cout<<A[i]<<" ";
cout<<A[n-1];//注意最后没有空格
}