例如: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; } 複製代碼