[Leetcode]316.去除重複字母

AdamWong發表於2019-01-04

題目

貪心方法

用一個兩個陣列vector<int>cnt,vector<bool>in_right_place;

string res:目前符合條件的字串,到程式碼結束的時候,這個res才是正確的答案

 

cnt陣列 用於記錄每個char未來會出現的次數,in_right_place陣列判斷這個char是否已經在正確的位置上

什麼叫做未來會出現呢?

我們拿樣例做為例子:

輸入: "bcabc"

我們先遍歷一遍所有字串記錄cnt

結果是cnt['a']=1,cnt['b']=2,cnt['c']=2,其他都為0

我們需要再遍歷一遍尋找結果

現在讀到第一個字元b,未來會出現的'b'的次數就減去1(因為已經出現了一次了),所以未來b只會再出現(2-1)次,這就是未來出現的次數

 

in_right_place判斷正確位置比較好理解,我們每次讀到一個未在正確位置上的字元,就可以將這個字元拿來和res比較字典序,

如果能發現存在一個新字串使得字典序更小,則代替

 

如何判斷字典序更小呢?

通過這個:

while(cnt[res.back()]>0&&讀取的當前字元<res.back()){
/*就能說明存在一個新序列使得字典序更小*/
in_right_place[res.back()]=false;
res.pop_back();
/*撤銷正確位置的標記並將其從結果字串彈出*/
}

還是回到樣例,假設當前讀取的字元為s[2],即'a',此時的res="bc"

=>‘a’比'c'字典序優先且'c'未來還會出現(即cnt['c']>0),說明存在'a'在'c'前面的搭配,所以彈出'c'並撤銷'c'是正確位置的標記即in_right_place['c']=false;此時res="b"

=>‘a’比'b'字典序優先且'b'未來還會出現(即cnt['b']>0),說明存在'a'在'b'前面的搭配,所以彈出'b'並撤銷'b'是正確位置的標記即in_right_place['b']=false;此時res=""

 

這一題的貪心在於,每次遍歷會考慮後面的情況將res改變。具體實現程式碼如下:

 

C++實現程式碼如下:

class Solution {
public:
    string removeDuplicateLetters(string s) {
        vector<int>cnt(256);
        vector<bool>in_right_place(256);
        for(char c:s){
            cnt[c]++;
        }
        string res="";
        /*返回的字串初始化為空*/
        for(char c:s){
            cnt[c]--;
            if(in_right_place[c]){
                /*如果已經在正確位置,則跳過*/
                continue;
            }else{
                while(cnt[res.back()]>0&&c<res.back()){
                    /*說明存在一個新序列使得字典序更小*/
                    in_right_place[res.back()]=false;
                    res.pop_back();
                    /*撤銷正確位置的標記並將其從結果字串彈出*/
                }
                res+=c;
                in_right_place[c]=true;
                /*此時c在“當前的”正確位置*/
            }
        }
        return res;
        
    }
};

也可以不用vector而用陣列記錄

class Solution {
public:
   string removeDuplicateLetters(string s) {
        int m[256] = {0}, visited[256] = {0};
        string res = "";
        for (auto a : s) m[a]++;
        for (auto a : s) {
            --m[a];
            if (visited[a]) continue;
            while (a < res.back() && m[res.back()]) {
                visited[res.back()] = 0;
                res.pop_back();
            }
            res += a;
            visited[a] = 1;
        }
        return res;
    }
};

 

相關文章