其他分享
首页 > 其他分享> > 316. 去除重复字母

316. 去除重复字母

作者:互联网

题目描述:

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

 

示例 1:

输入:s = "bcabc"
输出"abc"

示例 2:

输入:s = "cbacdcbc"
输出:"acdb"

 

提示:

 

解题思路:单调栈解法

用一个单调栈维护字典序最小的字符串。由于对每个出现过的字母必须保证出现在最终的字符串中,直接遍历不确定当前出栈的字母后续是否还会出现,需要首先用字典存储每个字母出现的次数,在做出栈操作的时候,若当前字母的剩余出现次数非大于0,则即使不满足单调性该字母也必须进栈。

 

由于只包含小写字母,因此可以用26大小的vector来存储字母出现的次数,同理需要用一个vis数组保存当前字母是否已经在栈中,若已经在,就不需要重复进栈。

 

复杂度:由于遍历一遍字符串,且每个字母仅进出栈一次,时间复杂度O(n),空间复杂度:用了栈结构,O(n)

 

代码:

class Solution {
public:
    string removeDuplicateLetters(string s) {
        int n = s.length();
        if(n <= 1)
            return s;
        vector<int> flag(26, 0);
        vector<int> vis(26, 0);
        for(int i=0; i<n; i++) {
            flag[s[i]-'a']++;
        }
        
        stack<char> mystack;
        for(int i=0; i<n; i++) {
            while(!mystack.empty() && s[i] < mystack.top() && vis[s[i]-'a'] == 0) {
                if(flag[mystack.top()-'a'] > 0) {
                    vis[mystack.top()-'a'] = 0;
                    mystack.pop();
                } else {
                    break;
                }
            }
            if(vis[s[i]-'a'] == 0) {
                mystack.push(s[i]);
                vis[s[i]-'a'] = 1;
            }
            
            flag[s[i]-'a']--;
        }
        
        string res;
        while(!mystack.empty()) {
            res += mystack.top();
            mystack.pop();
        }
        
        reverse(res.begin(), res.end());
        
        return res;
    }
};

  

 

标签:26,res,字母,316,vis,去除,字符串,mystack
来源: https://www.cnblogs.com/LJ-LJ/p/16026653.html