---
# System prepended metadata

title: 0316. Remove Duplicate Letters (Medium)
tags: [LeetCode, Duplicate]

---

###### tags: `LeetCode` `Duplicate`

# 0316. Remove Duplicate Letters (Medium)
耗時：>60 分鐘 (看別人解答)

## 題目
Given a string s, remove duplicate letters so that every letter appears once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.

## 思路
1. 一開始考慮以循序判斷的方式解析字串，或是以substring的方式divide and conquer，但始終有考慮上的死角，雖然有想到unique(僅有一個的字母，不能被刪除)，但沒有成功解題。

2. 別人解答的思路總結：在unique前的最小字母就是該子字串的解！
    以pos為當前字母，循序找出較小的字母，並重新以他為字串起始點
    若找到unique，則遞迴判斷子字串
    
    舉例來說：cbacdacbc, d為unique，因此我們可以分解為S1:(~~cb~~a)，S2:(cdacbc)，S1中的a為最小字母，且於unique前，則a為S1的唯一解(**不會有比a小的字母無法被刪除**)
    

* Time Complexity：O(n)
* Space Complexity：O(n^2)
    * Worst Case：全部字母皆為unique, space= n + (n-1) + (n-2) + ... + 1 = O(n^2)

### 程式碼
參考別人的解答：
```
class Solution {
public:
    string removeDuplicateLetters(string s) {
        int cnt[26] = {0};
        int pos = 0;
        for (int i = 0; i < s.length(); ++i) cnt[s[i] - 'a']++;
        for (int i = 0; i < s.length(); ++i) {
            // find smaller head
            if (s[i] < s[pos])
                pos = i;
            // find unique number
            if (--cnt[s[i] - 'a'] == 0)
                break;
        }
        if (s.length() - pos > 0) {
            string sub = s.substr(pos+1);
            string sub_2 = "";
            for (int i = 0; i < sub.length(); ++i)
                if (sub[i] == s[pos])
                    sub[i] = '_';
                else
                    sub_2.push_back(sub[i]);
            return  s[pos] + removeDuplicateLetters(sub_2);
        }
        else
            return "";
    }
};
```