NC115.栈和排序_C++题解

原题链接:链接

代码:
 

class Solution {
    private:
    vector<int>ret;
    int hash[50010] = {0};
    stack<int>st;
public:
    vector<int> solve(vector<int>& a) {
        int aim = a.size();
        for(auto x:a){
            st.push(x);
            hash[x] = true;
            while(hash[aim]){
                aim--;
            }
            while(st.size()&&st.top()>=aim){//while(st.size()&&st.top>aim)
                ret.push_back(st.top());
                st.pop();
            }
        }
        return ret;
    }
};

读完题之后,我们会发现,必须让vector<int> a中最大的元素先出栈,其他任何一个比它小的元素都不好使,同时我们发现题目中说明了vector<int> a是一个1-n的排列,所以a.size()就是我们苦苦寻找的最大值,我们只需要守株待兔,等它进栈,然后st.pop();即可;比如vector<int> a = {2,3,1,4,5};此时a.size()==5 , 同时max_val==5;我们在代码中用int aim = a.size();来初始化;

此外,我们用数组模拟哈希表来记录我们要的元素是否已经在栈中:int hash[] = {0};当val进栈,我们就hash[val] = true; 

第一次我们见到aim也就是最大值进了栈【此时hash[aim]==true】,我们就知道了得把它弹出去,但是下一次弹谁呢?应该是4!也就是aim-1那个值,但是如果4也已经进栈了【hash[aim--]==true】呢?那么我们还需要把4给弹出去,假设4和5中间还是其他元素,比如3,没关系,我们写一个while循环,一次性直接把aim更新到已经进栈的元素中与aim能连续的元素即可。比如栈中有2 4 5,那么aim更新到3即可,我们发现hash[3]==false;那么就进入下一个循环,也就是弹出操作,弹出之前别忘了把元素push_back到一个ret数组中,题目要求返回一个vector<int>,所以我们用ret记录答案。

出栈的这一部分代码我们用另一个vector<int> a = {3,2,1,,5,4} ;  来模拟。aim初始化为5,3 2 1则顺利进栈,遇到5我们发现找到了aim,所以while循环中aim更新为4,我们发现hash[4]==false;所以进入下一个部分,我们把5弹出,然后上去继续取数,拿到了4,while(hash[aim])成立,进入循环,aim更新为3,我们发现3也在栈中,同样的2,1都在栈中,aim更新为0,进入下一个循环,按理来说,我们把3拿出来就行了,可惜了这是栈,我们得按照规则来,你想要的5 4 3 2 1确实是字典序最大,但这在本题中是不可能实现的!这是这道题的关键!我们比如把大于等于aim的值全部弹出来,没办法做到3 2 1的顺序出栈。但这已经是字典序最大了。我们等待到4的时候,我们就知道下一个拿出来3是最好的,但是3已经被压在了最下边,你如果想拿到3,你必须把2 1 先拿出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值