蓝桥杯第十三届决赛真题-左移右移

article/2025/9/17 22:02:44

左移右移

  • 一、思路分析
  • 二、数组模拟双链表❗️❗️
  • 三、代码展示

题目链接

问题描述

小蓝有一个长度为 N 的数组, 初始时从左到右依次是 1,2,3, …N 。
之后小蓝对这个数组进行了 M 次操作, 每次操作可能是以下 2 种之一:
左移 x, 即把 x 移动到最左边。
右移 x, 即把 x 移动到最右边。
请你回答经过 M 次操作之后, 数组从左到右每个数是多少?

输入格式

第一行包含 2 个整数, N 和 M。
以下 M 行每行一个操作, 其中 “L x "表示左移 x, "R x "表示右移 x 。

输出格式

输出 N 个数, 代表操作后的数组。

样例输入

5 3
L 3
L 2
R 1

样例输出

2 3 4 5 1

样例说明
样例中的数组变化如下:

[1,2,3,4,5]→[3,1,2,4,5]→[2,3,1,4,5]→[2,3,4,5,1]
评测用例规模与约定
对于50% 的评测用例, 1 ≤ N,M ≤ 10000.
对于 100% 的评测用例,1 ≤ N,M ≤ 200000,1 ≤ x ≤ N.

运行限制

最大运行时间:3s
最大运行内存: 512M

一、思路分析

首先最容易想的的办法就是创建一个数组,把1 - N的数字放进去,然后按照后面输入的字符(LR)和数字来操作:先找到数字,再挪动到头部或者尾部。
但是我们发现这种算法的时间复杂度是O(N ^ 2),而且这道题也会时间超时。那么下面就引入用数组模拟双链表的方法:

二、数组模拟双链表❗️❗️

在前面的文章我们讲过双向链表,用链表进行插入就可以不用挪动数据,但是我们发现查找数据还得遍历,那样又会变成O(N ^ 2),所以我们可以采用数组模拟。
先用一张图来演示:
假设我们要模拟这样一个链表:
在这里插入图片描述
现在我们用数组模拟就需要三个数组:一个是存放数值的数组,一个是记录节点左边位置的数组,一个是记录节点右边位置的数组。

	int e[MAX];// 节点数据int l[MAX];// 记录当前节点的左节点int r[MAX];// 记录当前节点的右节点int index;// 记录e下一个要插入的位置

我们让e的第0个位置代替head,第一个位置代替tail。
那么真实的结构是这样的:
在这里插入图片描述
红的的数字就是我们首先要初始化的地方,也就是让我们找到头和尾。

而且index也需要初始化成2,因为0 和 1 的位置已经被占了,只能从下标2的位置开始插入。
构造函数:

	mylist(): index(2){// 0位置表示头,1位置表示尾l[1] = 0;r[0] = 1;}

在pos位置的右边插入数字:
在这里插入图片描述
绿线表示链接的顺序,注意3和4的顺序不能变

	// 在pos的右边插入void insert(int pos, int x){// 先插入到e中e[index] = x;// 四根线l[index] = pos;r[index] = r[pos];l[r[pos]] = index;r[pos] = index;index++;}

针对这道题目为了方便我们直接加一个尾插的成员函数:

	void push_back(int x){e[index] = x;l[index] = l[1];r[index] = 1;r[l[1]] = index;l[1] = index;index++;}

删除节点:
首先要知道并不是真的把当前位置清理,而是让pos位置的左右位置的 l 和 r 改变。我们就可以发现删除并不影响e数组中的数据相对位置

	// 并不是真的删除void pop(int pos){// 左右互连r[l[pos]] = r[pos];l[r[pos]] = l[pos];}

从左向右打印:
怎么找到head?

r[0]

	void print(){for (int i = r[0]; i != 1; i = r[i]){cout << e[i] << " ";}cout << endl;}

这道题我们还需要挪动数据,所以再写个成员函数:

	// 将pos位置的数字挪到最左/右边void move(char ch, int pos){// 先删除pos位置(l和r)pop(pos);// 设置pos位置的l和rif (ch == 'L'){l[pos] = 0;r[pos] = r[0];l[r[0]] = pos;r[0] = pos;}else{l[pos] = l[1];r[pos] = 1;r[l[1]] = pos;l[1] = pos;}}

通过这里我们就发现这道题用数组模拟链表的好处了:
比方说我们要找3,那么下标就是4,而且就算把3移动了,改变的也是 l 和 r 数组,不会影响e,再找下一个数字也可以这么找。

整个类的代码:

class mylist
{
public:mylist(): index(2){// 0位置表示头,1位置表示尾l[1] = 0;r[0] = 1;}// 在pos的右边插入void insert(int pos, int x){// 先插入到e中e[index] = x;// 四根线l[index] = pos;r[index] = r[pos];l[r[pos]] = index;r[pos] = index;index++;}void push_back(int x){e[index] = x;l[index] = l[1];r[index] = 1;r[l[1]] = index;l[1] = index;index++;}// 并不是真的删除void pop(int pos){// 左右互连r[l[pos]] = r[pos];l[r[pos]] = l[pos];}void print(){for (int i = r[0]; i != 1; i = r[i]){cout << e[i] << " ";}cout << endl;}// 将pos位置的数字挪到最左/右边void move(char ch, int pos){// 先删除pos位置(l和r)pop(pos);// 设置pos位置的l和rif (ch == 'L'){l[pos] = 0;r[pos] = r[0];l[r[0]] = pos;r[0] = pos;}else{l[pos] = l[1];r[pos] = 1;r[l[1]] = pos;l[1] = pos;}}private:int e[MAX];// 节点数据int l[MAX];// 记录当前节点的左节点int r[MAX];// 记录当前节点的右节点int index;// 记录e下一个要插入的位置
};

三、代码展示

#include <iostream>
using namespace std;const int MAX = 200002;class mylist
{
public:mylist(): index(2){// 0位置表示头,1位置表示尾l[1] = 0;r[0] = 1;}// 在pos的右边插入void insert(int pos, int x){// 先插入到e中e[index] = x;// 四根线l[index] = pos;r[index] = r[pos];l[r[pos]] = index;r[pos] = index;index++;}void push_back(int x){e[index] = x;l[index] = l[1];r[index] = 1;r[l[1]] = index;l[1] = index;index++;}// 并不是真的删除void pop(int pos){// 左右互连r[l[pos]] = r[pos];l[r[pos]] = l[pos];}void print(){for (int i = r[0]; i != 1; i = r[i]){cout << e[i] << " ";}cout << endl;}// 将pos位置的数字挪到最左/右边void move(char ch, int pos){// 先删除pos位置(l和r)pop(pos);// 设置pos位置的l和rif (ch == 'L'){l[pos] = 0;r[pos] = r[0];l[r[0]] = pos;r[0] = pos;}else{l[pos] = l[1];r[pos] = 1;r[l[1]] = pos;l[1] = pos;}}private:int e[MAX];// 节点数据int l[MAX];// 记录当前节点的左节点int r[MAX];// 记录当前节点的右节点int index;// 记录e下一个要插入的位置
};int main()
{int n, m;cin >> n >> m;mylist list;// 放数据for(int i = 1; i <= n; i++){list.push_back(i);}char ch;int num;// 挪动数据while(m--){cin >> ch >> num;list.move(ch, num + 1);}list.print();return 0;
}

http://chatgpt.dhexx.cn/article/9CeXvbSb.shtml

相关文章

C语言左移右移操作符详解

看到过很多C语言中的移位操作相关的博文&#xff0c;但是这些博文之间的深度实在是差别太大了&#xff0c;对于初学者来说&#xff0c;想要弄明白移位操作并不容易&#xff0c;有的博文仅仅是讲了怎么进行位移&#xff0c;初学者可能会因此写下bug&#xff0c;有的博文虽然到位…

彻底理解位运算——左移、右移

相信大家在各种语言各种框架中都能看到二进制的操作。左移、右移、&、|、^等等操作。那么这篇帖子让各位彻底弄懂左移、右移。 首先先区分那个是左移、那个是右移&#xff0c;这很简单&#xff0c;从箭头指向的方向来区分。<<左移&#xff0c;>>右移 左移&am…

汉诺塔

2019独角兽企业重金招聘Python工程师标准>>> 伪算法&#xff1a; 如果是1个盘子 直接将A柱子上的盘子从A移到C 否则 先将A柱子上的n-1个盘子借助C移到B <?php function hannuota($n,$a,$b,$c){if ($n1) {echo 盘子 .$n. 直接从柱子 .$a. 移动到柱子 .$c.<br/…

汉诺塔Java递归实现

2019独角兽企业重金招聘Python工程师标准>>> 算法逻辑&#xff1a; 利用递归&#xff0c;当n为1时为递归出口&#xff0c;通过改变柱子的位置实现 当只有一个盘子时是从a&#xff08;初始&#xff09;->c&#xff08;目的&#xff09; 当有n个盘子时 先 &#x…

汉诺塔------java算法

这其实是一个递归问题&#xff0c;下面是用Java对汉诺塔的实现。 源代码&#xff1a; 方式一&#xff1a; import java.util.Scanner;/***BelongsProject: javaSenior*BelongsPackage: PACKAGE_NAME*Author: 48-zj*CreateTime: 2023-04-13 22:09*Description: TODO*Version:…

数据结构与算法之递归

直接或间接地调用自身的算法称为递归算法。 通过这种递推关系把原来问题缩小成一个更小规模的同类问题&#xff0c;并延续这一缩小规模的过程&#xff0c;直到在某一规模上&#xff0c;问题的解是已知的。这样一种解决问题的思想我们称为递归的思想。 常见题目1&#xff1a; …

递归详解-斐波那契、汉诺塔、青蛙跳台阶、字符串长度

递归-斐波那契数列 这里我们讲解一下 斐波那契数列的经典递归问题。 斐波那契数列&#xff1a; 1 1 2 3 5 8 13 21 34… 从第三个数字开始&#xff0c;下一个数字等于前面两个数字之后&#xff0c;有点像我们数学的数列 n(x-1)n(x-2) 那如果我们要求第n个数字&#xff0c;应该…

HDU - 1995 汉诺塔V 难度:递归入门 复杂度:有点复杂

方案一&#xff08;公式法&#xff09; 我还不清楚用递归来解汉诺塔问题是怎么解&#xff0c;对递归比较陌生&#xff0c;但后来发现这题可以不用递归&#xff0c;套用下面发现的公式即可。 一个盘 1号1次 两个盘 1号2次 2号1次 三个盘 1号4次 2号2次 3号1次 四个盘…

【Python学习】Python解决汉诺塔问题

摘要&#xff1a; 参考文章&#xff1a;http://www.cnblogs.com/dmego/p/5965835.html 一句话&#xff1a;学程序不是目的&#xff0c;理解就好&#xff1b;写代码也不是必然&#xff0c;省事最好&#xff1b;拿也好&#xff0c;查也好&#xff0c;解决问题就好&#xff01; 信…

C++ 汉诺塔程序实现

2019独角兽企业重金招聘Python工程师标准>>> 首先不看代码&#xff0c;汉诺塔解题步骤有三步&#xff08;设A->C&#xff09;&#xff0c;先将汉诺塔看成两部分n-1,1(n-1在上面) 第一&#xff1a;将A中的n-1个盘借助C移到B >Hanoi(n-1,a,c,b); 第二&#xff…

【算法与数据结构】汉诺塔

数据结构里的汉诺塔&#xff0c;递归的典型代表&#xff0c;几乎讲到递归都会讲到汉诺塔&#xff0c;今天才把汉诺塔看明白&#xff0c;惭愧啊。 不废话了&#xff0c;贴代码&#xff0c;基本思想在注释里有&#xff0c;话说往CNBLOG首页投了两次&#xff0c;两次都被小编给扯下…

递归-汉诺塔

2019独角兽企业重金招聘Python工程师标准>>> 递归&#xff08;recursion&#xff09;&#xff1a;程序调用自身的编程技巧。 反复执行的过程&#xff08;调用自身&#xff09;有跳出反复执行过程的条件&#xff08;递归出口&#xff09; import com.lifeibigdata.al…

汉诺塔问题

2019独角兽企业重金招聘Python工程师标准>>> 前提说明&#xff1a; ‍算法&#xff1a;当只有一个盘子的时候&#xff0c;只需要从将A塔上的一个盘子移到C塔上。 当A塔上有两个盘子是&#xff0c;先将A塔上的1号盘子&#xff08;编号从上到下&#xff09;移动到B塔上…

JavaScript算法实现之汉诺塔(Hanoi)

目前前端新手&#xff0c;看到的不喜勿喷&#xff0c;还望大神指教。 随着Node.js&#xff0c;Angular.js,JQuery的流行&#xff0c;点燃了我学习JavaScript的热情&#xff01;以后打算每天早上跟晚上抽2小时左右时间将经典的算法都用JS来实现&#xff0c;加快学习JS的步伐&…

【C语言】递归的经典问题(模拟strlen,阶乘,斐波那契数列,汉诺塔,青蛙跳台阶)

以下我分享的是关于C语言递归的比较经典的题&#xff0c;有些题提供了多种解法&#xff0c;希望可以帮助你打开思路&#xff0c;如果你有更多的解法&#xff0c;欢迎评论区留言哟~ 目录 一、输入1234&#xff0c;输出1 2 3 4 二、模拟strlen功能 1&#xff09;递归 2&…

7.递归-汉诺塔

汉诺塔问题&#xff1a; 如果求解的汉诺塔是3层&#xff0c;可以先将上面的两层看作是一个整体。先将两层经过c作为中介移动到b&#xff0c;再将第三个圆盘直接移动到c。然后再将b上面的两个圆盘移动到c&#xff0c;通过a为中介。 算法分析&#xff08;递归算法&#xff09; 我…

数据结构与算法之汉诺塔问题

2019独角兽企业重金招聘Python工程师标准>>> 一、汉诺塔问题 1.汉诺塔问题 起源&#xff1a;一位法国数学家曾编写过一个印度的古老传说&#xff1a;在世界中心贝拿勒斯的圣庙里&#xff0c;一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候&#xff…

汉诺塔 最优算法设计商量

2019独角兽企业重金招聘Python工程师标准>>> 引言 汉诺塔算法一向是算法设计科目标最具代表性的研究题目&#xff0c;本文存眷于如何设计多柱汉诺塔最优算法的商量。最简单的汉诺塔是三个柱子&#xff08;A、B、C&#xff09;&#xff0c;是以多柱汉诺塔的柱子个数M…

函数递归与汉诺塔

C初阶之函数递归 函数递归基本原理 什么是递归&#xff1f;程序调用自身的编程技巧称为递归recursion。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法&#xff0c;它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解&#xff0c;…

分治算法的解和幂乘算法及其优化以及汉诺塔算法的介绍

分治算法就是分成若干个和原问题一样性质的子问题&#xff0c;然后逐步递归这些子问题&#xff0c;直到遇到规模很小的子问题&#xff0c;求出子问题的解&#xff0c;归结成原问题的解的算法就是分治算法 分治算法为递归问题&#xff0c;可以用来解决快排、二分归并、斐波那契数…