华为机试—火车进站

题目

火车站一共有 n 辆火车需要入站,每辆火车有一个编号,编号为 1 到 n。
同时,也有火车需要出站,由于火车站进出共享一个轨道,所以后入站的火车需要先出站。换句话说,对于某一辆火车,只有在它之后入站的火车都出站了,它才能出站。
现在,已经知道了火车的入站顺序,你需要计算,一共有多少种不同的出站顺序。按照字典序从小到大依次输出全部的出站顺序。

示例

输入:3

           1 2 3

输出:

1 2 3
1 3 2
2 1 3
2 3 1
3 2 1

说明:

在这个样例中,每一种出栈顺序的详细出入站状况为(黑色字体代表入站、粉色字体代表出站):
∙1→1→2→2→3→3;
∙1→1→2→3→32;
∙1→2→21→3→3;
∙1→2→2→3→31;
∙1→2→3→321。
输出若干行,每行输出 n 个整数,代表一种出站顺序。你需要按照字典序从小到大依次输出。

分析

这是一个关于栈操作和全排列的问题,我们可以使用深度优先搜索(DFS)算法结合栈来解决。

DFS

算法思路

我们使用一个栈来模拟火车的入站和出站操作。初始时,栈为空,我们从入站序列的第一个火车开始处理。

在每一步,我们有两种选择:

  • 将当前入站的火车入栈。
  • 如果栈不为空,将栈顶的火车出站。

使用深度优先搜索(DFS)来遍历所有可能的入栈和出栈操作组合。

当入站序列中的所有火车都已入站,并且栈为空时,我们得到了一种合法的出站顺序。将所有合法的出站顺序存储在一个数组中,并按照字典序从小到大输出。

时间复杂度:O(2^{n}\times n)

空间复杂度:O(\frac{4^{n}}{\sqrt{n}})

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

// 深度优先搜索函数
void dfs(vector<int>& inSeq, stack<int>& st, vector<int>& outSeq, vector<vector<int>>& allOutSeqs) {
    // 如果入站序列和栈都为空,说明找到了一种合法的出站顺序
    if (inSeq.empty() && st.empty()) {
        allOutSeqs.push_back(outSeq);
        return;
    }
    // 如果入站序列不为空,将当前火车入栈
    if (!inSeq.empty()) {
        int temp = inSeq.front();
        inSeq.erase(inSeq.begin());
        st.push(temp);
        dfs(inSeq, st, outSeq, allOutSeqs);
        inSeq.insert(inSeq.begin(), temp);
        st.pop();
    }
    // 如果栈不为空,将栈顶火车出站
    if (!st.empty()) {
        int temp = st.top();
        st.pop();
        outSeq.push_back(temp);
        dfs(inSeq, st, outSeq, allOutSeqs);
        outSeq.pop_back();
        st.push(temp);
    }
}

int main() {
    int n;
    cin >> n;
    vector<int> inSeq(n);
    for (int i = 0; i < n; ++i) {
        cin >> inSeq[i];
    }
    stack<int> st;
    vector<int> outSeq;
    vector<vector<int>> allOutSeqs;
    dfs(inSeq, st, outSeq, allOutSeqs);
    // 按照字典序排序
    sort(allOutSeqs.begin(), allOutSeqs.end());
    // 输出所有出站顺序
    for (const auto& seq : allOutSeqs) {
        for (int num : seq) {
            cout << num << " ";
        }
        cout << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rigidwill666

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值