洛谷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;
}
运行结果

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

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

相关推荐
王维同学2 小时前
[自学][Windows C++]RunOnceEx 注册表分组键的安全遍历
c++·windows·安全·开源
战族狼魂2 小时前
高频面试题精选:分治与AI Agent架构
人工智能·算法·大模型·大语言模型
李剑一3 小时前
你用过网易的将军令嘛?它底层实现账号保护的原理相当简单粗暴
算法
Scott9999HH3 小时前
告别流量波动玄学!从法拉第电磁定律到底层 C/C++ 流量累积算法,深度解密工业级电磁流量计选型与开发
c语言·c++·算法
中达瑞和-高光谱·多光谱3 小时前
1nm到8nm光谱分辨率,你的应用该选哪款光谱相机?
算法·高光谱·高光谱相机
脱胎换骨-军哥3 小时前
C++/Rust无缝互操作:混合系统新常态
开发语言·c++·rust
ChaoZiLL4 小时前
我的数据结构4-栈和队列
数据结构
香辣牛肉饭4 小时前
【算法】动态规划 最长公共子序列(LCS)
经验分享·笔记·算法·动态规划
miller-tsunami4 小时前
顺序表相关知识点
数据结构·顺序表