题目:
题目简意:
给你 n 个数,并且任意给定的数都属于 [1,k]。
请你求出字典序最小的一组 k 的排列,并且为给定数组的子序列。
分析:
注意到题目的数据范围需要一个小于 O(n^2) 的方法。
考虑到题目要求答案的字典序最小,我们需要用一个容器存储答案,而在实现过程中有可能当前答案并不是最优解,所以这个容器需要容易改动,因此想到用栈的先进后出机制来存储答案。
接下来由于答案需要是 k 的一个排列,所以不能有重复元素,所以我们创建一个容器记录这个元素是否已经计入答案中。
我们还需要再创建一个数组来存储每个型号最后出现的位置,这样防止跳过了它的最后一个位置,还没有将他放入答案里这不是很尴尬,所以我们需要创建这个数组,来看一下跳过当前这个位置后面这个型号还会不会出现。
具体实现步骤:
遍历邦布型号的序列 x,我们对于这个 x 中的每个元素都检查一下他在不在栈里已经出现过,如果出现过的话就直接跳过这个元素进入下一个元素。
还有为了保证答案字典序最小,我们如果当前这个元素大于栈顶的元素的时候,我们就把栈顶元素弹出然后把哈希表里的这个元素也要移除。
最后输出就行了。
代码就不放那么详细了,因为讲解都快把代码放出来了:
/*输入*/
/*初始化记录最后出现位置的数组*/
/*输入,并且记录最后出现的位置*/
stack<int>st;//最后我们的答案
unordered_set<int>in;//哈希表
for(int i=0;i<n;i++){
if(/*如果这个元素已经被加入答案*/){
//跳过
}
while(/*如果当前元素小于栈顶并且后面还会出现栈顶所代表的元素*/){
/*删除栈顶,并且在哈希表中删除栈顶所代表的元素*/
}
/*将当前元素入栈,并且存入哈希表*/
}
vector<int>res;//答案
while(!st.empty()){
/*由于栈是先进后出的所以我们还需要把它正过来*/
}
/*输出*/
实现复杂度:
由于每个元素都只遍历了一次,故复杂度为 O(n) 可在 1 秒内通过本题。