Leetcode 316. 去除重复字母(中等) 1081. 不同字符的最小子序列(中等) 字符串去重

labuladong讲解

316. 去除重复字母(中等)

题目:

 

 思路:

题目的要求总结出来有三点:

要求一、要去重。

要求二、去重字符串中的字符顺序不能打乱 s 中字符出现的相对顺序。

要求三、在所有符合上一条要求的去重字符串中,字典序最小的作为最终结果。

比如说输入字符串 s = "babc",去重且符合相对位置的字符串有两个,分别是 "bac" 和 "abc",但是我们的算法得返回 "abc",因为它的字典序更小。

我们可以借用单调栈的思路,在放入元素c时踢出大于c的元素。

但是踢出的条件是,如果count[d]>0,即后续仍旧有d可以加入。

 

class Solution {
public:
    string removeDuplicateLetters(string s) {
        // 维护一个计数器记录字符串中字符的数量
        // 因为输入为 ASCII 字符,大小 256 够用了
        vector<int> count(256);
        for(int i=0;i<s.size();++i){
            count[s[i]]++;
        }
        //记录字符是否已进栈
        vector<bool> inStack(256);
        stack<char> stk;
        for(int i=0;i<s.size();++i){
            char c=s[i];
            // 每遍历过一个字符,都将对应的计数减一
            count[c]--;
            //如果已进栈,就直接跳过
            if(inStack[c]){
                continue;
            }
            //如果栈顶元素大于c,对栈顶元素操作
            while(!stk.empty()&&stk.top()>c){
                // 若之后不存在栈顶元素了,则停止 pop
                if(count[stk.top()]==0){
                    break;
                }
                // 若之后还有,则可以 pop
                inStack[stk.top()]=false;
                stk.pop();
            }
            stk.push(c);
            inStack[c]=true;
        }
        //反序取出栈内元素组合成字符串
        string ret;
        while(!stk.empty()){
            ret=stk.top()+ret;
            stk.pop();
        }
        return ret;
    }
};

 

1081. 不同字符的最小子序列(中等)

与上题完全相同

posted @ 2022-02-28 16:29  鸭子船长  阅读(124)  评论(0编辑  收藏  举报