PTA(栈和队列)2-2 列车厢调度
PTA(栈和队列)2-2 列车厢调度
zhangzhang2-2 列车厢调度
分数 5
作者 周强
单位 青岛大学
1 | 1 ====== <--移动方向 |
大家或许在某些数据结构教材上见到过“列车厢调度问题”(当然没见过也不要紧)。今天,我们就来实际操作一下列车厢的调度。对照上方的ASCII字符图,问题描述如下:
有三条平行的列车轨道(1、2、3)以及1-3和2-3两段连接轨道。现有一列车厢停在1号轨道上,请利用两条连接轨道以及3号轨道,将车厢按照要求的顺序转移到2号轨道。规则是:
- 每次转移1节车厢;
- 处在1号轨道的车厢要么经过1-3连接道进入3号轨道(该操作记为”1->3”),要么经过两条连接轨道直接进入2号轨道(该操作记为”1->2”);
- 一旦车厢进入2号轨道,就不可以再移出该轨道;
- 处在3号轨道的车厢,只能经过2-3连接道进入2号轨道(该操作记为”3->2”);
- 显然,任何车厢不能穿过、跨越或绕过其它车厢进行移动。
对于给定的1号停车顺序,如果经过调度能够实现2号轨道要求的顺序,则给出操作序列;如果不能,就反问用户 Are(你) you(是) kidding(凯丁) me(么)?
输入格式:
两行由大写字母组成的非空字符串,第一行表示停在1号轨道上的车厢从左到右的顺序,第二行表示要求车厢停到2号轨道的进道顺序(输入样例1中第二行CBA表示车厢在2号轨道的停放从左到右是ABC,因为C最先进入,所以在最右边)。两行字符串长度相同且不超过26(因为只有26个大写字母),每个字母表示一节车厢。题目保证同一行内的字母不重复且两行的字母集相同。
输出格式:
如果能够成功调度,给出最短的操作序列,每个操作占一行。所谓“最短”,即如果1->2可以完成的调度,就不要通过1->3和3->2来实现。如果不能调度,输出 “Are you kidding me?”
输入样例1:
1 | ABC |
输出样例1:
1 | 1->3 |
输入样例2:
1 | ABC |
输出样例2:
1 | Are you kidding me? |
我的思路:
相当于1中的字符是即将入栈(2)的,可以暂存到3这个栈中,也可以直接出栈到(结果)2中
相当于让你写进出栈顺序的,让你写成最佳的
- 即如果1->2可以完成的调度,就不要通过1->3和3->2来实现
- 最后一个进去的如果没进去,就不进去了,直接就出栈了(1->2)
先检查当前放入的是不是结果中匹配的,
- 如果不是,往栈中放1->3,每次
getTop一次,检查是否跟结果数组中的一样,不一样就重复第一步 - 如果是直接1->2,不入栈
- 然后当前栈非空就
getTop,检查栈顶是否是匹配的,匹配就3->2 - 不匹配或栈空就重复第一步,没有元素了就失败了
- 然后当前栈非空就
- 如果不是,往栈中放1->3,每次
我的问题:万一前面的能匹配,最后匹配不了了,我都已经输出了一半了,咋还只输出Are you kidding me?
我想到了解决办法,可以先存起来存队列里面,然后不符合的话前面的就不输出,哦不对,要输出的是从哪到哪
我的乱思路代码
代码思路方向是对的(用栈模拟 3 号轨道)
1 |
|
- 核心逻辑:1 号轨道的车厢需按顺序处理,要么直接进入 2 号轨道(1->2),要么先进入 3 号轨道暂存(1->3),之后从 3 号轨道进入 2 号轨道(3->2)。最终需让 2 号轨道的车厢顺序与目标一致。
- 关键错误:
- 栈中元素匹配时,错误地用了当前 1 号轨道的车厢(
c)去比较,而应使用栈顶元素。 - 处理完 1 号轨道所有车厢后,未检查栈中剩余元素是否能按顺序进入 2 号轨道。
- 未判断最终是否完全匹配,导致无法输出 “Are you kidding me?”。
- 栈中元素匹配时,错误地用了当前 1 号轨道的车厢(
- 豆包是让输出序列先存到string里面,不匹配就不输出
正确答案
1 |
|
java版
- string类型——String引用类型
- 输入:
- 需创建
Scanner对象,通过scanner.next()读取
- 需创建
栈的实现:
| 维度 | C++ 版本 | Java 版本 |
|---|---|---|
| 栈的类选择 | 直接使用 std::stack<char> 类 |
推荐使用 Deque<Character>(双端队列)模拟栈(java.util.Stack 是遗留类,不推荐) |
| 入栈操作 | stack.push(current) |
deque.push(current)(与 C++ 同名,但类不同) |
| 出栈操作 | stack.pop()(无返回值) |
deque.pop()(无返回值,与 C++ 行为一致) |
| 获取栈顶元素 | stack.top() |
deque.peek()(Java 中 peek() 对应栈顶查询,top() 不存在) |
| 判空操作 | stack.empty() |
deque.isEmpty()(方法名差异,语义一致) |
| 栈的初始化 | stack<char> Stack3;(直接声明) |
Deque<Character> stack3 = new ArrayDeque<>();(接口 + 实现类,需实例化) |
集合类
Deque<Character>只能存储对象,不能直接存储基本类型char,所以用CharacterDeque的本质:Deque是 Java 中的 “双端队列” 接口(全称Double Ended Queue),它允许在队列的两端进行添加 / 删除操作(既可以从头部操作,也可以从尾部操作)。用
Deque模拟栈的原理:栈的核心是 “后进先出(LIFO)”,只需要在
Deque的同一端(比如尾部)进行 “入栈” 和 “出栈” 操作,就能模拟栈的行为:- 入栈:
push(element)→ 向Deque的尾部添加元素(相当于栈的 “压栈”)。 - 出栈:
pop()→ 从Deque的尾部移除并返回元素(相当于栈的 “弹栈”)。 - 查看栈顶:
peek()→ 返回Deque的尾部元素(不删除,相当于栈的 “查看栈顶”)。
- 入栈:
字符串操作:
C++ 中
str1[i]对应 Java 的str1.charAt(i)字符串拼接使用
StringBuilder(比String直接拼接更高效)StringBuilder的作用:Java 中的String是 “不可变的”(一旦创建就不能修改内容),如果直接拼接字符串(比如s = s + "1->2"),会频繁创建新的String对象,效率很低。StringBuilder是专门用于高效拼接字符串的类,它的内容可以修改,避免了频繁创建对象的开销。append()方法:StringBuilder的核心方法,用于向当前字符串中 “追加” 内容(可以是字符串、字符、数字等),直接修改自身,不创建新对象。
编译错误答案
1 | Compiler did not create the expected binary |
- 不知道哪错了(idea也没报错)
1 | import java.util.ArrayDeque; |


