Leetcode (316) Remove Duplicate Letters

本文介绍了一个算法问题,即如何从给定的字符串中移除所有重复的字母,并确保最终字符串的字典序是最小的。文章详细解释了贪心策略的应用,并提供了C++实现代码。
  • 题目:

Given a string which contains only lowercase letters, remove duplicate letters so that every letter appear once and only once. You must make sure your result is the smallest in lexicographical order among all possible results.

Example:
Given “bcabc”
Return “abc”

Given “cbacdcbc”
Return “acdb”

  • 题意:给定一个字符串,要求移除字符串中的重复字母,最后使得最后的字符串字典序最小,返回该字符串。
  • 思路:

    • 考虑实例字符串”cbacdcbc”得到“acdb”的方式。之所以,第一个字母是’a’,是因为’cb’在后面还有,将’a’放在最开头比’bc’放在最开头字典序要小。
    • 再考虑为什么’b’只能放到最后,原因就是’b’后面没有’d’,因此只能在前面取得’d’。
    • 于是,很容易得到一个贪心策略,如果当前字母想放到前面使得字典序变小的话,只需要保证它往前移的过程中间的所有字母在后面仍然有即可。
    • 而考虑”aybx”字典序小于”axyb”,因此往前移时应当一直往前,直到后面没有那个字母为止,才能保证能够往前移动到一个最佳的位置。
  • 代码

class Solution {
public:
    string removeDuplicateLetters(string s) {
        int cnt[128]={0};
        for (auto ch: s)
        {
            cnt[ch]++;
        }

        bool has[128]={false};
        string ans(26, ' ');
        int len=0;
        for (auto ch: s)
        {
            cnt[ch]--;
            if (has[ch]) continue;
            int idx=len-1, pos=len;
            // 找到最佳位置
            while (idx>=0 && cnt[ans[idx]] > 0)
            {
                if (ans[idx] > ch)
                {
                    pos=idx;
                }

                idx--;
            }
            // 前移过程
            while (len > pos)
            {
                has[ans[len-1]] = false;
                len--;
            }

            len = pos+1;
            ans[pos] = ch;
            has[ch] = true;
        }
        return ans.substr(0, len);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值