316. 去除重复字母

博客围绕处理仅含小写字母的字符串展开,要求去除重复字母,使每个字母仅出现一次,且返回结果字典序最小,同时不能打乱字符相对位置。给出示例及自身代码超时、网上代码 12ms 的情况。

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

示例 1:

输入: “bcabc”
输出: “abc”
示例 2:

输入: “cbacdcbc”
输出: “acdb”

我的代码 超时

class Solution {
public:
    string min_s="zzzzzzz";
    int search(string s,char c)
    {
        for(int i=0;i<s.size();i++)
            if(s[i]==c)
                return i;
        return -1;
    }
    void dfs(string temp,string &s,int t)
    {
        if(s.size()==t)
        {
            if(temp<min_s)
                min_s=temp;
            return;
        }
        int index=search(temp,s[t]);
        if(index==-1)
        {
            temp+=s[t];
            dfs(temp,s,t+1);
        }
        else
        {
            string old=temp;
            old.erase(index,1);
            string news=temp+s[t];
            news.erase(index,1);
            dfs(news,s,t+1);
           if(news>old)
           {
                dfs(temp,s,t+1);
           }
            
        }
         
    }
    string removeDuplicateLetters(string s) {
        if(s.size()==0) return s;
       string t="";
        t+=s[0];
       dfs(t,s,1);
    
        return min_s;
    }
};

网上的代码 12ms

class Solution {
public:
    string removeDuplicateLetters(string s) {
        //m[i]用于标记字符i出现了过少次
        //visited[i]用于标记字符i是否已经写入结果
        int m[256] = {0}, visited[256] = {0};
        string res = "0";
        //第一次扫描字符串,标记各个字符出现的次数
        for (auto a : s){
            m[a] += 1;
        }
        //第二次扫描字符串,写入结果
        for (auto ch : s) {
            m[ch] -= 1;//出现的次数自减
           if (visited[ch])//如果这个字符已经写入结果
              continue;
            //如果出现比res之前写入的字符还小的字符,且这个写入的字符之后还出现过
            while (ch < res.back() && m[res.back()]) {
                //将之前写入的记过倒出
                visited[res.back()] = 0;
                res.pop_back();
            }
            res += ch;//写入
            visited[ch] = 1;//标记已写入
        }
        return res.substr(1);//去掉开头的字符0
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值