316. 去除重複字母

tsuiraku發表於2020-12-21

316. 去除重複字母

難度:中等???


給你一個字串 s ,請你去除字串中重複的字母,使得每個字母只出現一次。需保證 返回結果的字典序最小(要求不能打亂其他字元的相對位置)。

**注意:**該題與 1081 https://leetcode-cn.com/problems/smallest-subsequence-of-distinct-characters 相同

示例 1:

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

示例 2:

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

提示:

  • 1 <= s.length <= 104
  • s 由小寫英文字母組成

題解:

貪心 + 棧 + 雜湊表

比如 字串 s='bac',刪除一個字元如何使得得到字典序最小?

解決方法是:遍歷字串 s ,當滿足 s[i]>s[i+1] 的時候,刪除 i 即可得到最小 ,我們將這個字串記住作 關鍵字元

第一種最直接的想法是:遍歷字串,找到 關鍵字元 ,然後去除它 ,但是效率不高

有沒有更優化的解法呢?

嘗試一下做法,以 s = "bcabc" 為例:

遇到 b ,入棧 ,遇到 c ,入棧(滿足字典序列就可以直接入棧);

遇到 a ,此時棧頂部元素為 c ,現在我們站在上帝視角可以看見字串後面還有 c ,因此可以將棧頂元素 c 彈出 ; 此時棧頂元素為 b ,字串後面依然還有 b ,也將其彈出;此時棧已經空了,將 a 入棧;

遇到 b 滿足字典序,入棧;

遇到 c 滿足字典序,入棧;

最終的結果為 abc

c++

class Solution {
public:
    string removeDuplicateLetters(string s) {
        string st;
        vector<int> vis(26),mp(26);
        for(int i = 0;i < s.size();i++)
        {
            mp[s[i] - 'a']++;
        }

        for(int i = 0;i < s.size();i++)
        {
            if(!vis[s[i] - 'a'])
            {
                while(!st.empty() && st.back() > s[i])
                {
                    if(mp[st.back() - 'a'] > 0)
                    {
                        vis[st.back() - 'a'] = 0;
                        st.pop_back();
                    }
                    else break;
                }
                vis[s[i] - 'a'] = 1;
                st.push_back(s[i]);
            }
            mp[s[i] - 'a'] -= 1;
        }

        return st;
    }
};

python

class Solution:
    def removeDuplicateLetters(self, s: str) -> str:
        from collections import Counter
        mp = Counter(s)
        vis = set()
        st = []
        for i in range(len(s)):
            if s[i] not in vis:
                while len(st) > 0 and st[-1] > s[i]:
                    if mp[st[-1]] > 0:
                        vis.remove(st[-1])
                        st.pop()
                    else:
                        break
                vis.add(s[i])
                st.append(s[i])
            mp[s[i]] -= 1

        return "".join(st)

參考:

相關文章