【ACWing】129. 火车进栈

题目地址:

https://www.acwing.com/problem/content/description/131/

这里有 n n n列火车将要进站再出站,但是,每列火车只有 1 1 1节,那就是车头。这 n n n列火车按 1 1 1 n n n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。也就是说这个火车站其实就相当于一个栈,每次可以让右侧头火车进栈,或者让栈顶火车出站。车站示意如图:

        出站<——    <——进站
                 |车|
                 |站|
                 |__|

现在请你按字典序输出前 20 20 20种可能的出栈方案。

输入格式:
输入一个整数 n n n,代表火车数量。

输出格式:
按照字典序输出前 20 20 20种答案,每行一种,不要空格。

数据范围:
1 ≤ n ≤ 20 1≤n≤20 1n20

每列火车有三个状态,入站前,在站中,已出站。我们考虑按字典序搜索答案,每次搜的时候,尽量让编号小的列车在出站序列的前面。当站里有车的时候,优先将其出站,然后DFS进入下一层;如果站里没车,则只能将新车入站。当已出站序列长度为 n n n的时候即得到了一个答案。代码如下:

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

int n;
vector<int> post_stk;
stack<int> in_stk;
int pre_stk = 1;
int cnt;

void dfs() {
  if (cnt == 20) return;

  if (post_stk.size() == n) {
    for (int x : post_stk) printf("%d", x);
    puts("");
    cnt++;
    return;
  }

  if (in_stk.size()) {
    post_stk.push_back(in_stk.top());
    in_stk.pop();
    dfs();
    in_stk.push(post_stk.back());
    post_stk.pop_back();
  }

  if (pre_stk <= n) {
    in_stk.push(pre_stk++);
    dfs();
    in_stk.pop();
    pre_stk--;
  }
}

int main() {
  scanf("%d", &n);
  dfs();
}

时间复杂度 O ( 2 n ) O(2^n) O(2n),空间 O ( n ) O(n) O(n)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
为了判断通过一个能否得到指定的出序列,可以采用模拟法。具体做法如下: 1. 定义一个,初始为空; 2. 依次将1~n压入中,每次操作后判断是否需要弹出顶元素; 3. 如果当前顶元素等于出序列中下一个应该弹出的元素,就弹出它并将出序列指针后移一位; 4. 最终如果为空并且出序列指针已经指向了最后一个元素,说明能够得到指定的出序列,否则不能。 下面是实现上述算法的 Python 代码: ```python def is_valid_pop_order(push_order, pop_order): stack = [] push_index, pop_index = 0, 0 while push_index < len(push_order): stack.append(push_order[push_index]) push_index += 1 while stack and stack[-1] == pop_order[pop_index]: stack.pop() pop_index += 1 return len(stack) == 0 and pop_index == len(pop_order) # 测试 print(is_valid_pop_order([1, 2, 3, 4, 5], [4, 5, 3, 2, 1])) # True print(is_valid_pop_order([1, 2, 3, 4, 5], [4, 3, 5, 1, 2])) # False ``` 在上述代码中,is_valid_pop_order函数接收两个参数push_order和pop_order,分别表示序列和出序列。函数中定义了一个stack,以及两个指针push_index和pop_index,分别用于记录序列和出序列中已经处理过的位置。 具体实现时,每次将一个元素压入中,并检查是否需要弹出顶元素。如果当前顶元素等于出序列中下一个应该弹出的元素,就弹出它并将出序列指针后移一位。最终如果为空并且出序列指针已经指向了最后一个元素,说明能够得到指定的出序列,否则不能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值