例如:cfebfacb算法
经过上面的思路走一遍例子:cfebfacb 处理点+子串数组
结果:ceabmarkdown
char* delDuplicateLetters(char *string) { //1.记录字母出现的次数 int arr[26] = {0}; for (int i = 0; i < strlen(string); i++) { arr[string[i] - 'a'] ++; } //2.遍历循环字符串中的字符,每找到一个字符,对应的字母出现次数的数组中记录的出现次数--,当出现的次数减到0,说明后面不会再出现,顺便也记录一下当前遍历到的元素中,最小的元素的位置 int pos = 0; for (int i = 0; i < strlen(string); i++) { if (string[i] < string[pos]) { pos = i; } if (--arr[string[i] - 'a'] == 0) { break; } } //3.获取有消失字符以前的最小字符的位置 char *t = (char*)malloc(sizeof(char)); *t = string[pos]; //4.根据最小字符的位置为分割点,截取后面子字符串 char subString[strlen(&string[pos + 1])]; //5.删除子串中,全部的上面循环记录中的最小元素 strcpy(subString, &string[pos + 1]); int j = 0; for (int i = 0; subString[i] != '\0'; i++) { if (subString[i] != string[pos]) { subString[j++] = subString[i]; } } subString[j]='\0'; //6.递归和出口 return (strlen(string) == 0) ? "" : strcat(t, delDuplicateLetters(subString)); } int main(int argc, const char * argv[]) { // insert code here... printf("Hello, World!\n"); char *str = delDuplicateLetters("dbcbcab"); printf("%s\n", str); return 0; } 复制代码
使用栈的方式实现-参考代码中的注释数据结构
代码中的栈操做,请参考文章 数据结构-栈代码实现post
char* stringDelChar(char *string, char chr) { char *ret = (char*)malloc(sizeof(char) * strlen(string)); int j = 0; for (int i = 0; i < strlen(ret); i++) { if (chr != ret[i]) { ret[j++] = ret[i]; } } ret[j] = '\0'; return ret; } char* delDuplicateLetters(char *string) { //1.字符串中的字符最后一次出现的位置 int lastPos[26] = {0}; for (int i = 0; i < strlen(string); i++) { lastPos[string[i] - 'a'] = i; } //2.初始化 栈 SqStack stack; initStack(&stack); //3.建立一个字符串,里面存放已经入栈的字符,至关于一个容器 char *set = (char*)malloc(sizeof(char) * strlen(string)); //4.开始遍历 for (int i = 0; i < strlen(string); i++) { char c = string[i]; //5.当前字符是否已经在容器中 char *isHas = strchr(set, c); if (!isHas) { SElemType topElem; getTopElem(stack, &topElem); //6.栈不为空 当前字符小于栈顶字符 该字符不是最后一次出现 while (!isEmptyStack(stack) && c < *topElem && lastPos[c] > i) { //7.出栈,出容器 SElemType temp; popElemFromStack(&stack, &temp); set = stringDelChar(set, *temp); } //8.入栈,入容器 strcat(set, &c); SElemType temp = (SElemType)malloc(sizeof(char)); *temp = '\0'; strcpy(temp, &c); pushElem2Stack(&stack, temp); } } //遍历栈,新的字符串 char *ret = (char*)malloc(sizeof(stack.top)); for (int i = 0; i <= stack.top; i++) { SElemType c = stack.data[i]; strcat(ret, c); } free(set); return ret; } int main(int argc, const char * argv[]) { // insert code here... printf("Hello, World!\n"); char *str = delDuplicateLetters("cbacdcbc"); printf("%s\n", str); return 0; } 复制代码
最近学习到更加简洁的代码,总体思路和上面的栈实现同样,我的认为比个人写法更简洁的点是对c语言更透彻一些。直接上代码,代码中有我我的的注释。学习
char *removeDuplicateLetters(char *s) { if (strlen(s) <= 1) { return s; } //字符出现次数数组 char record[26] = {0}; //初始化栈 int len = (int)strlen(s); char *stack = (char*)malloc(sizeof(char) * 2 * len); memset(stack, 0, sizeof(char) * 2 * len); int top = -1; //循环遍历存入字符出现的次数 for (int i = 0; i < len; i++) { record[s[i]-'a']++; } //循环遍历字符串中的字符 for (int i = 0; i < len; i++) { //字符是否存在栈中 int isExist = 0; for (int j = 0; j <= top; j++) { if (s[i] == stack[j]) { isExist = 1; break; } } if (isExist == 1) { //字符存在栈中,把记录数组相关的记录-- record[s[i] - 'a']--; } else { //开始循环遍历,条件:栈不为空 && 栈顶元素大于当前字符 && 记录数组中当前字符的记录大于1(也就是后面还会有这个字符出现) while (top > -1 && stack[top] > s[i] && record[stack[top]-'a'] > 1) { //字符记录-- record[stack[top]-'a']--; //出栈 top--; } //入栈当前字符 stack[++top] = s[i]; } } //最后给字符加入结束点 stack[++top] = '\0'; return stack; } int main(int argc, const char * argv[]) { // insert code here... printf("Hello, 去除重复字符-栈!\n"); char *str = delDuplicateLetters("cbacdcbc"); printf("%s\n", str); char *str1 = removeDuplicateLetters("cbacdcbc"); printf("%s\n", str1); return 0; } 复制代码