题目描述
我们称一个数列 p 是一个长度为 n 的排列,当且仅当 p 满足如下条件:
- p 的长度为 n;
- 1,2,3,...n 这 n 个数在 p 中均恰好出现一次。
对于一个排列 p,定义一次"shift"操作是指:将 p 里的每一个数字都依次向后移动一位,并把 p 的最后一个数字移动到开头去。
例如,若排列 p 初始时为 [1,4,2,3],则"shift"一次以后将变为 [3,1,4,2]。
现在,给定一个长度为 n 的排列 p,请你按照如下规定循环操作:
- 对当前的排列 p 做一次"shift"操作;
- 输出本次"shift"以后的排列 p;
- 判断排列 p 的最后一个数字是否是 n,如果是,则结束循环操作;否则回到 1 继续操作。
提示:请严格按照题目给出的顺序进行循环操作。
输入
第一行是一个整数,表示排列 p 的长度 n。
第二行有 n 个整数表示排列 p,第 i 个整数表示 pi。
输出
对于每次操作的第二条"输出"操作,请你输出一行 n 个整数,按顺序表示当前排列的每个数,一行中相邻两个数之间用一个空格隔开。
样例输入输出
输入 #1
4
1 4 2 3
输出 #1
3 1 4 2
2 3 1 4
输入 #2
3
1 2 3
输出 #2
3 1 2
2 3 1
1 2 3
输入 #3
10
1 7 6 5 8 4 3 9 10 2
输出 #3
2 1 7 6 5 8 4 3 9 10
思路
题目中的操作,可以理解为把序列中最后一个元素移到最前面,直到最后一个元素是n。
在STL中,有一种容器可以很方便地进行此操作:deque(双端队列)。
先介绍一下deque,deque的常用操作有:
01.元素访问
cpp
deque<int>d={1,2,3,4,5};
d[2]; //下标访问,不检查边界,O(1)
d.at(2); //带边界检查的访问,越界抛出out_of_range,O(1)
d.front(); //访问第一个元素,O(1)
d.back(); //访问最后一个元素,O(1)
02.容量操作
cpp
d.empty(); // 判断是否为空,O(1)
d.size(); // 返回元素个数,O(1
03.修改操作
cpp
//插入
d.push_back(6); // 尾部添加,O(1)
d.push_front(0); // 头部添加,O(1)
d.insert(pos,val); // 在指定位置插入,O(n)
d.insert(pos,n,val); // 插入n个val
d.insert(pos,first,last);// 插入迭代器区间元素
//删除
d.pop_back(); // 删除尾部元素,O(1)
d.pop_front(); // 删除头部元素,O(1)
d.erase(pos); // 删除指定位置元素,O(n)
d.erase(first, last); // 删除区间元素,O(n)
d.clear(); // 清空所有元素,O(n)
//其他
d.assign(5, 10); // 重新赋值为5个10
d.assign({1,2,3}); // 重新赋值为初始化列表
d.swap(d2); // 交换两个deque的内容
d.resize(10); // 改变大小
d.resize(10, 5); // 改变大小并用5填充新位置
关于题目,还有一个细节:
因为题目是先做操作才判断,所以循环时应该用do......while循环 !!!
至此题目分析完毕,下面展示步骤:
STEP 1:按要求输入,把输入的元素插进双端队列中。
STEP 2:do......while循环,每次记上然后删除队尾元素,插入队头。
STEP 3:for:循环遍历输出队列元素即可。
代码
cpp#include<bits/stdc++.h> using namespace std; int n,a; deque<int>q; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>a; q.push_back(a); } do { a=q.back(); q.pop_back(); q.push_front(a); for(int v:q) { cout<<v<<' '; } cout<<'\n'; }while(q.back()!=n); return 0; }运行结果

感谢阅读,我们下期再会。
如果您喜欢本文,请您点赞、收藏加关注,以防你找不到回来的路,谢谢!