leetcode-316去除重复字母

998 阅读1分钟

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

示例 1:

输入: "bcabc"
输出: "abc"

示例 2:

输入: "cbacdcbc"
输出: "acdb"

思路

去除字符中重复的字母很容易,难点在于如何保证返回结果的字典序最小。 实例1bca不符合条件就是因为abc字典序小于bca

我们可以利用栈来实现,确保栈中是最小字典序。在入栈的过程中,如果栈顶元素大于s[i]并且栈顶元素在索引i后面还有,就可以出栈,然后将s[i]入栈。

cbacdcbc    
1. c入栈                -->  c
2. c出栈b入栈           -->  b
3. b出栈a入栈           -->  a
4. c入栈                -->  ac
5. d入栈                -->  acd
6. c已经有了continue    -->  acd
7. b虽然小于d,但是后面已经没有d了,d不能出栈,b入栈   -->  acdb
8. c已经有了continue    -->  acdb
#define MAXSIZE 128
bool IsContain(char *stack, char a, int len)
{
    for (int i = 0; i <= len; i++) {
        if (stack[i] == a) {
            return true;
        }
    }
    return false;
}
char *removeDuplicateLetters(char *s)
{
    int len = strlen(s);
    int hash[MAXSIZE] = {0};
    for (int i = 0; i < len; i++) {
        hash[s[i]] = i;
    }
    char *stack = (char *)calloc(len+1, sizeof(char));
    int top = -1;
    for (int i = 0; i < len; i++) {
        if (!IsContain(stack, s[i], top)) {
            while (top > -1 && stack[top] > s[i] && hash[stack[top]] > i) {
                top--;
            }
            top++;
            stack[top] = s[i];
        }
    }
    return stack;
}