模考 T8 题解

题目:

screenshotnoscale163beb8a-2ac9-4310-a503-f23ff7ee3230

题目简意:

给你 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 秒内通过本题。

2 个赞