大厂笔试真题【栈】美团2023春招-火车迷【欧弟算法】全网最全大厂秋招题解

文章目录

  • 题目描述与示例
    • 题目描述
    • 输入描述
    • 输出描述
    • 示例一
      • 输入
      • 输出
    • 示例二
      • 输入
      • 输出
  • 解题思路
  • 代码
    • python
    • Java
    • C++
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

题目描述与示例

题目描述

小美是一个火车迷。最近她在观察家附近火车站的火车驶入和驶出情况,发现火车驶入和驶出的顺序并不一致。经过小美调查发现,原来这个火车站里面有一个类似于栈的结构,如下图所示:

大厂笔试真题【栈】美团2023春招-火车迷【欧弟算法】全网最全大厂秋招题解_第1张图片

例如可能1号火车驶入了火车站中的休息区s,在驶出之前2号火车驶入了。那么在这种情况下,1号火车需要等待2号火车倒车出去后才能出去(显然被后面驶入的2号火车挡住了,这个休息区s只有一个出入口)。

出于好奇,小美统计了近些天的火车驶入驶出情况,开始统计和结束统计时休息区s中均是空的。由于中途疏忽,小美觉得自己好像弄错了几个驶入驶出顺序,想请你帮她验证一下。

值得注意的是,小美虽然可能弄错了顺序,但对火车的记录是不重不漏的。

形式化地来形容休息区s,我们视其为一个容量无限大的空间,假设两列火车 ij 同时处于休息区s中,驶入时刻Tin满足Tin(i),则驶出时间Tout必定满足Tout(i)>Tout(j),即,先进后出。

输入描述

第一行输入一个整数T表示数据组数。

对每组测试而言:

第一行输入一个整数n,表示观察到的火车数量。

第二行输入n个整数x1,x2,...,xn,表示小美记录的火车驶入休息区s的顺序。

第三行输入n个整数y1,y2,...,yn,表示小美记录的火车驶出休息区s的顺序。

1 ≤ T ≤ 101 ≤ n ≤ 500001 ≤ xi, yi ≤n, 且{xn}{yn} 均为{1,2,3,...,n}的一个排列,即1~nn个数在其中不重不漏恰好出现一次。

输出描述

对每组数据输出一行:如果小美记录的驶入和驶出顺序无法被满足则输出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的行为,一共有两种可能性:

  1. A直接驶入B
  2. A驶入S

我们设置一个B区的索引idx_BB_list[idx_B]表示B区即将驶入的车厢编号

AB_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循环中进行。

大厂笔试真题【栈】美团2023春招-火车迷【欧弟算法】全网最全大厂秋招题解_第2张图片

代码

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 
#include 

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了解更多

你可能感兴趣的:(大厂秋招真题,#,栈,算法,leetcode,python,面试)