唯一入栈出库序列(C++/Py/Java /Js/Go)题解
拼多多 8月30号 笔试真题 第二题
拼多多真题目录点击查看: 拼多多 春招&秋招 笔试真题题库目录|笔试题库 + 算法考点详解
题目内容
中转仓今晚只有一条暂存滑轨,滑轨按栈工作:后进的货先出。值班员必须按货号从小到大出库,并记下唯一的入轨、出库动作;若做不到就在日志里写失败标记。
共有 k k k 件货按到达顺序经过主道,第 i i i 件的货号是 v i v_i vi。 v v v 是 1 ∼ k 1 \sim k 1∼k 的一个排列。出库顺序必须恰好是 1 , 2 , ... , k 1,2,\dots,k 1,2,...,k。
每件货到达时,值班员必须立刻做下面两种动作之一:
I:把它推进暂存栈;- 若规则允许,之后用
O弹出栈顶出库。
任意时刻只要栈顶正好是下一个该出的货号,就必须立刻O出库。可以证明:能成功时,动作序列是唯一的。
请判断能否按号出完。能则输出由I和O组成的动作串(恰好 k k k 个I和 k k k 个O);不能则输出N。
货件数满足 1 ≤ k ≤ 1 \le k \le 1≤k≤200000。
输入描述
第一行一个正整数 k k k( 1 ≤ k ≤ 1 \le k \le 1≤k≤ 200000),表示货件数。
第二行 k k k 个正整数 v 1 , v 2 , ... , v k v_1,v_2,\dots,v_k v1,v2,...,vk,保证是 1 ∼ k 1 \sim k 1∼k 的排列。
输出描述
若存在合法方案,输出一行由 I 和 O 组成的字符串;否则输出一行一个字符 N。
样例1
输入
4
3 1 2 4
输出
IIOIOOIO
说明
3、1 入栈后弹出 1,再让 2 入栈并连续弹出 2、3,最后 4 入栈再出库。
样例2
输入
3
2 3 1
输出
N
说明
2、3 入栈后,1 再入再出,栈顶变成 3,下一个该出的是 2,卡死。
样例3
输入
1
1
输出
IO
说明
只有一件货,入栈后立刻出库。
题解
思路
解题算法:栈
- 记录当前需要弹出的数
index,使用栈保存压入的数,ans记录处理序列 - 循环接受输入的数,并压入栈中,同时添加
I操作,如果当前栈顶元素 == index,迭代弹出栈顶元素,并添加O操作。 - 处理完所有输入数之后,如果栈非空说明无合法序列输出
N.否则输出对应ans序列即可。 - 算法总体时间复杂度为
O(k)
C++
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
int k;
string ans;
int index = 1;
stack<int> stk;
cin >> k;
for (int i = 0; i < k; i++) {
int x;
cin >> x;
stk.push(x);
ans.push_back('I');
while (!stk.empty() && stk.top() == index) {
ans.push_back('O');
stk.pop();
index++;
}
}
if (!stk.empty()) {
cout << "N";
return 0;
}
cout << ans;
return 0;
}
java
java
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
StringBuilder ans = new StringBuilder();
int index = 1;
Stack<Integer> stk = new Stack<>();
for (int i = 0; i < k; i++) {
int x = sc.nextInt();
stk.push(x);
ans.append('I');
while (!stk.empty() && stk.peek() == index) {
ans.append('O');
stk.pop();
index++;
}
}
if (!stk.empty()) {
System.out.print("N");
return;
}
System.out.print(ans);
}
}
python
python
k = int(input())
data = list(map(int, input().split()))
ans = []
index = 1
stk = []
for i in range(k):
x = data[i]
stk.append(x)
ans.append('I')
while stk and stk[-1] == index:
ans.append('O')
stk.pop()
index += 1
if stk:
print("N")
else:
print(''.join(ans))
javascript
js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const input = [];
rl.on('line', line => {
input.push(...line.trim().split(/\s+/));
});
rl.on('close', () => {
let pos = 0;
const k = Number(input[pos++]);
let ans = [];
let index = 1;
const stk = [];
for (let i = 0; i < k; i++) {
const x = Number(input[pos++]);
stk.push(x);
ans.push('I');
while (stk.length > 0 && stk[stk.length - 1] === index) {
ans.push('O');
stk.pop();
index++;
}
}
if (stk.length > 0) {
console.log('N');
return;
}
console.log(ans.join(''));
});
Go
go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
in := bufio.NewReader(os.Stdin)
var k int
fmt.Fscan(in, &k)
ans := ""
index := 1
stk := []int{}
for i := 0; i < k; i++ {
var x int
fmt.Fscan(in, &x)
stk = append(stk, x)
ans += "I"
for len(stk) > 0 && stk[len(stk)-1] == index {
ans += "O"
stk = stk[:len(stk)-1]
index++
}
}
if len(stk) > 0 {
fmt.Println("N")
return
}
fmt.Println(ans)
}