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

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

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

相关推荐
得物技术7 分钟前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六3 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术4 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize5 小时前
初识DFS 与 BFS:递归、队列与图遍历
算法
罗西的思考18 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
CSharp精选营21 小时前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode