洛谷B3688:[语言月赛202212]旋转排列(新解法:deque双端队列)

题目描述

我们称一个数列 p 是一个长度为 n 的排列,当且仅当 p 满足如下条件:

  1. p 的长度为 n;
  2. 1,2,3,...n 这 n 个数在 p 中均恰好出现一次。

对于一个排列 p,定义一次"shift"操作是指:将 p 里的每一个数字都依次向后移动一位,并把 p 的最后一个数字移动到开头去。

例如,若排列 p 初始时为 [1,4,2,3],则"shift"一次以后将变为 [3,1,4,2]。

现在,给定一个长度为 n 的排列 p,请你按照如下规定循环操作:

  1. 对当前的排列 p 做一次"shift"操作;
  2. 输出本次"shift"以后的排列 p;
  3. 判断排列 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;
}
运行结果

感谢阅读,我们下期再会。

如果您喜欢本文,请您点赞、收藏加关注,以防你找不到回来的路,谢谢!

相关推荐
Zachery Pole1 小时前
【代码随想录】二叉树
算法
漂流瓶jz2 小时前
UVA-11214 守卫棋盘 题解答案代码 算法竞赛入门经典第二版
c++·算法·dfs·aoapc·算法竞赛入门经典·迭代加深搜索·八皇后
浮生09192 小时前
DHUOJ 基础 88 89 90
算法
fpcc3 小时前
并行编程实战——CUDA编程的Enhancing Memory Allocation
c++·cuda
v_for_van3 小时前
力扣刷题记录7(无算法背景,纯C语言)
c语言·算法·leetcode
先做个垃圾出来………3 小时前
3640. 三段式数组 II
数据结构·算法
白太岁3 小时前
通信:(3) 高并发网络通信:epoll + 边沿触发 + 非阻塞 IO + tcp
c语言·网络·c++·网络协议·tcp/ip
楼田莉子3 小时前
C++项目:日志&&线程池
linux·c++·学习·visual studio code
tankeven4 小时前
HJ93 数组分组
c++·算法