[Leetcode]316.去除重复字母

题目

贪心方法

用一个两个数组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;
    }
};
原文地址:https://www.cnblogs.com/adamwong/p/10219690.html