leetcode 316. 去除重复字母【单调栈 官方题解补充:为何要判断栈中是否有当前元素】

该博客探讨了C++实现字符串中不重复字符最小字典序排列的方法。通过使用栈和辅助数组,确保在遇到重复字符时,栈顶的字符在字典序上大于后续可能出现的字符。错误的处理方式可能导致字典序变大,正确的策略是让后续字符逐一判断是否能形成更小的字典序。示例中,输入字符串'acfadcf'的正确输出应为'acdf',而非错误的'adcf'。
摘要由CSDN通过智能技术生成
class Solution {
public:
    
    string removeDuplicateLetters(string s) {
        vector<int> last(26,0);
        for(int i=0;i<s.size();i++){
            last[s[i]-'a'] = i;
        }

        stack<char>st;
        string ret = "";
        vector<bool> inst(26,0);

        for(int i=0;i<s.size();i++){
            int c = s[i];
            if( inst[c-'a']){
                continue;
            }

            while( !st.empty() ){
                char top = st.top();
                if( last[ top-'a' ] >= i && c <= top){
                    st.pop();
                    inst[top-'a'] = 0;
                }else{
                    break;
                }
            }
            
            st.push(c);
            inst[c-'a'] =1;
        }
        while(!st.empty()){
            char c = st.top();
            st.pop();
            ret = string(1,c) + ret;
        }
        return ret;
    }
};
在不去重的时候,就是栈中的元素有的时候也进行pop会有什么后果
输入
"acfadcf"
输出
"adcf"
预期结果
"acdf"

这一个样例,acf入栈之后,当前遇到第二个a,
如果不看栈里面是不是有a,就直接弹栈的话
这个时候就会把acf都弹出来,因为acf现在还有剩余的容量,
我们想的是,a(第二个)在栈顶遇到了f,后面出现过f,那么就可以把f弹出来,
但是如果栈中有a,如果你现在弹出来的f之后,就必须保证,
第二个a和后面的f区间的字串,比当前栈中的字串的字典序小
而这个是无法保证的,比如上面这个例子,把acf全部弹出去之后,后面的acdf的字典序比adcf大
所有正确的做法应该是跳出这个a,后面的字串能否比当前的字典序小,应该让后面的字串逐一判断
而不是在遇到a的时候就决定                                                                                                                                                                                                                                                                                                                                                                                                                                                    

正确的样例:

输入

"acfadcf"
输出
"acdf"
预期结果
"acdf"


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值