Early Orders
题目链接:牛客竞赛:https://ac.nowcoder.com/acm/problem/218908
题目大意:
给你一个长度为n的数组,求其中一个字典序最小长度为k的子序列,并且此子序列中每个数只出现一次(即为1到k).
测试数据:
输入
6 3
3
2
1
3
1
3
输出
2 1 3
输入
10 5
5
4
3
2
1
4
1
1
5
5
输出
3 2 1 4 5
解题思路:
遍历这个数组,对每个数据判断是否入栈,让栈为从小到大的顺序(除非当前数字在队列中为最后一个则必须入栈),同时已经入过栈的数据不能再次入栈,最后的结果即为最终答案.
代码(带注释):
#include<iostream>
using namespace std;
const int N = 200010;
int map[N];//用来标记当前数据在整个数组中还剩下几个
int q[N];//记录数组数据
int list[N];//模拟栈
int flag;//指向栈顶位置
bool vis[N];//标记当前数据是否已经入栈
int main()
{
int n, k;
cin >> n >> k;
//输入数组并且统计每个数据在数组中共出现几次
for (int i = 0; i < n; i++)
{
cin >> q[i];
map[q[i]]++;
}
//初始状态栈为空,无任何数据入栈
for (int i = 1; i <= k; i++)
{
vis[i] = false;
}
//遍利数组
for (int i = 0; i < n; i++)
{
int x = q[i];
map[x]--;
if (!vis[x])//判断是否已经入栈
{
while (x < list[flag] && map[list[flag]])//若栈顶大于当前数据且栈顶数据在之后还会出现则一直弹出栈顶
{
vis[list[flag--]] = false;//取消栈顶已入栈标记,并且弹出栈顶
}
//当前数据入栈
vis[x] = true;
list[++flag] = x;
}
}
//输出栈
for (int i = 1; i <= k; i++)
{
cout << list[i] << " ";
}
return 0;
}