文章目录
- 题目描述与示例
- 题目描述
- 输入描述
- 输出描述
- 示例一
- 输入
- 输出
- 示例二
- 输入
- 输出
- 解题思路
- 代码
- python
- Java
- C++
- 时空复杂度
- 华为OD算法/大厂面试高频题算法练习冲刺训练
题目描述与示例
题目描述
小美是一个火车迷。最近她在观察家附近火车站的火车驶入和驶出情况,发现火车驶入和驶出的顺序并不一致。经过小美调查发现,原来这个火车站里面有一个类似于栈的结构,如下图所示:
例如可能1
号火车驶入了火车站中的休息区s
,在驶出之前2
号火车驶入了。那么在这种情况下,1
号火车需要等待2
号火车倒车出去后才能出去(显然被后面驶入的2
号火车挡住了,这个休息区s
只有一个出入口)。
出于好奇,小美统计了近些天的火车驶入驶出情况,开始统计和结束统计时休息区s
中均是空的。由于中途疏忽,小美觉得自己好像弄错了几个驶入驶出顺序,想请你帮她验证一下。
值得注意的是,小美虽然可能弄错了顺序,但对火车的记录是不重不漏的。
形式化地来形容休息区s
,我们视其为一个容量无限大的空间,假设两列火车 i
和 j
同时处于休息区s
中,驶入时刻Tin
满足Tin(i)<Tin(j)
,则驶出时间Tout
必定满足Tout(i)>Tout(j)
,即,先进后出。
输入描述
第一行输入一个整数T
表示数据组数。
对每组测试而言:
第一行输入一个整数n
,表示观察到的火车数量。
第二行输入n个整数x1,x2,...,xn
,表示小美记录的火车驶入休息区s
的顺序。
第三行输入n个整数y1,y2,...,yn
,表示小美记录的火车驶出休息区s
的顺序。
1 ≤ T ≤ 10
,1 ≤ n ≤ 50000
,1 ≤ xi, yi ≤n
, 且{xn}
、{yn}
均为{1,2,3,...,n}
的一个排列,即1~n
这n
个数在其中不重不漏恰好出现一次。
输出描述
对每组数据输出一行:如果小美记录的驶入和驶出顺序无法被满足则输出No
,否则输出Yes
。
示例一
输入
3
3
1 2 3
1 2 3
3
1 2 3
3 2 1
3
1 2 3
3 1 2
输出
Yes
Yes
No
示例二
输入
3
4
1 2 4 3
1 2 3 4
9
1 2 3 4 5 6 7 8 9
3 2 1 6 5 4 9 8 7
4
1 2 3 4
3 2 1 4
输出
Yes
Yes
Yes
解题思路
注意这是一道非常经典的栈题,本质上和 LeetCode946. 验证栈序列 完全一致。本题有多种解法,只需懂得一种解法即可。
按照时间出现的顺序,考虑A_list
中的每一个元素A
的行为,一共有两种可能性:
A
直接驶入B
区A
驶入S
区
我们设置一个B
区的索引idx_B
,B_list[idx_B]
表示B
区即将驶入的车厢编号。
当A
和B_list[idx_B]
相等时,A
可以直接驶入B
区,否则应该驶入S
区进行等待。
当A
驶入B
区后,由于先前的idx_B
对应的车厢编号B_list[idx_B]
已经满足,故需要考虑B
区的下一个即将驶入的车厢,故idx_B
需要递增1
。
另外,由于idx_B
发生改变,我们需要考虑S
区中栈顶的车辆是否能够驶入B
区。若可以驶入,即stack[-1] == B_list[idx_B]
,则栈顶元素弹出且idx_B
继续递增。上述过程需要在while
循环中进行。
代码
python
# 题目:【栈】美团2023春招-火车迷
# 作者:闭着眼睛学数理化
# 算法:栈
# 代码有看不懂的地方请直接在群上提问
# 用于计算每次询问的函数
def cal(n, A_list, B_list):
# 初始化一个空栈
stack = list()
# 设置B_list中的索引idx_B,初始化为0
# B_list[idx_B]表示当前B区需要驶入的火车
idx_B = 0
# 遍历A_list中的每一节火车A
# A有两种选择:
# 1. 驶入B区;2. 驶入s区
for A in A_list:
# 若此时A与B_list中待驶入的火车不相等
# 则A需要驶入s区,等待后续操作
if B_list[idx_B] != A:
stack.append(A)
# 若此时A与B_list中待驶入的火车相等
# 则直接令A驶入B区
if B_list[idx_B] == A:
# idx_B递增,表示此时的A车已经驶入B区
idx_B += 1
# 接着需要检查栈顶元素stack[-1]是否和B_list[idx_B]相等
# 若相等,则将stack[-1]的元素驶入B区
while stack and idx_B < n and stack[-1] == B_list[idx_B]:
stack.pop()
idx_B += 1
# 如果最终stack为空,则说明所有火车都能够顺利进入B区,返回"Yes";否则返回False
# 这里的判断使用idx_B == n也是可以的
return "Yes" if len(stack) == 0 else "No"
# 输入询问次数
T = int(input())
ans = list()
# 询问T次
for _ in range(T):
# 分别输入三行
n = int(input())
A_list = list(map(int, input().split()))
B_list = list(map(int, input().split()))
ans.append(cal(n, A_list, B_list))
for s in ans:
print(s)
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int T = scanner.nextInt();
List<String> ans = new ArrayList<>();
for (int t = 0; t < T; t++) {
int n = scanner.nextInt();
int[] A_list = new int[n];
int[] B_list = new int[n];
for (int i = 0; i < n; i++) {
A_list[i] = scanner.nextInt();
}
for (int i = 0; i < n; i++) {
B_list[i] = scanner.nextInt();
}
ans.add(cal(n, A_list, B_list));
}
for (String s : ans) {
System.out.println(s);
}
}
static String cal(int n, int[] A_list, int[] B_list) {
List<Integer> stack = new ArrayList<>();
int idx_B = 0;
for (int A : A_list) {
if (B_list[idx_B] != A) {
stack.add(A);
}
if (B_list[idx_B] == A) {
idx_B++;
while (!stack.isEmpty() && idx_B < n && stack.get(stack.size() - 1) == B_list[idx_B]) {
stack.remove(stack.size() - 1);
idx_B++;
}
}
}
return stack.isEmpty() ? "Yes" : "No";
}
}
C++
#include <iostream>
#include <vector>
using namespace std;
string cal(int n, vector<int> &A_list, vector<int> &B_list) {
vector<int> stack;
int idx_B = 0;
for (int A : A_list) {
if (B_list[idx_B] != A) {
stack.push_back(A);
}
if (B_list[idx_B] == A) {
idx_B++;
while (!stack.empty() && idx_B < n && stack.back() == B_list[idx_B]) {
stack.pop_back();
idx_B++;
}
}
}
return stack.empty() ? "Yes" : "No";
}
int main() {
int T;
cin >> T;
vector<string> ans;
for (int t = 0; t < T; t++) {
int n;
cin >> n;
vector<int> A_list(n), B_list(n);
for (int i = 0; i < n; i++) {
cin >> A_list[i];
}
for (int i = 0; i < n; i++) {
cin >> B_list[i];
}
ans.push_back(cal(n, A_list, B_list));
}
for (string s : ans) {
cout << s << endl;
}
return 0;
}
时空复杂度
时间复杂度:O(Nt)
。每一个元素仅需进出栈一次。t
为询问次数。
空间复杂度:O(N)
。栈所占空间,每次询问后重置。
华为OD算法/大厂面试高频题算法练习冲刺训练
-
华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!
-
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
-
60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁
-
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
-
可查看链接 大厂真题汇总 & OD真题汇总(持续更新)
-
绿色聊天软件戳
od1336
了解更多