去除重复字母——LeetCode 316

279 阅读2分钟

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

解题思路:

  1. 遍历串的字符
  2. 判断栈中是否已有当前字符
    1. 如果已经栈里已存在,
      1. record内该字符出现的次数减一
      2. 继续遍历串的下一个字符
    2. 如果栈里不存在
      1. 循环 ( 栈不为空 + 栈顶字符>当前字符 + 栈顶字符的出现次数>1(即后面还会出现) ):
        1. record内该字符出现的次数减一
        2. 栈顶出栈
        3. 直到不满足循环
      2. 当前字符入栈
  3. 栈顶添加'\0' 构成字符串结尾字符(实际栈的存储空间还有其他字符,所以标记\0表示字符串结束)

代码

char *removeDuplicateLetters(char *s)
{
    if (s == NULL || strlen(s) == 0) return "";
    if (strlen(s) == 1) return s;
    
    // 准备工作:获取字符串长度、创建记录字符串线次数的数组record
    int len = (int)strlen(s);
    int record[26] = {0};
    
    // 创建栈,用于记录出现的字符
    char *stack = (char *)malloc(len * sizeof(char));
    memset(stack, 0, len * sizeof(char));
    // 栈顶置空
    int top = -1;
    
    // 统计字符串中每个字符出现的次数
    for (int i = 0; i < len; i++) {
        record[s[i]-'a']++;
    }
    
    
    // 遍历每个字符
    for (int i = 0; i < len; i++) {
        
        // 1、首先检查栈里是否已有该字符
        int isExit = 0;
        for (int j = 0; j <= top; j++) {
            if (stack[j] == s[i]) {
                isExit = 1;
                break;
            }
        }
        
        
        // 2、判断栈中是否已有当前字符
        // ① 如果已经栈里已存在该字符,
        //      ① record内该字符出现的次数减一
        //      ② 继续遍历串的下一个字符
        // ② 如果栈里不存在
        //      ① 循环 ( 栈不为空 + 栈顶字符>当前字符 + 栈顶字符的出现次数>1(即后面还会出现) ):
        //          ① record内该字符出现的次数减一
        //          ② 栈顶出栈
        //          ③ 直到不满足循环
        //      ② 当前字符入栈
        // 3、栈顶添加'\0' 构成字符串,处理完成,栈内元素从栈底到栈顶即为结果字符串
        if (isExit == 1)
        {   // ① 如果已经栈里已存在该字符,
            // ① record内该字符出现的次数减一
            record[s[i]-'a']--;
        }
        else
        {   // ② 如果栈里不存在
            while (top > -1 && stack[top] > s[i] && record[stack[top]-'a'] > 1)
            {   // ① 循环 ( 栈不为空 + 栈顶字符>当前字符 + 栈顶字符的出现次数>1(即后面还会出现) ):
                // ① record内该字符出现的次数减一
                record[stack[top]-'a']--;
                // ② 栈顶出栈
                top--;
            }
            
            top++;
            stack[top] = s[i];
        }
    }
    
    stack[++top] = '\0';
    
    return stack;
}
int main(int argc, const char * argv[]) {
    
    char *resultString;
    char *originString = "bcabc";
    printf("输入:%s\n",originString);
    resultString = removeDuplicateLetters(originString);
    printf("输出:%s\n",resultString);
    
    return 0;
}