LeetCode 316. Remove Duplicate Letters
最后输出结果中字母的顺序应该保留输入字符串中的顺序,而且字典序最小,比如输入"cbacdcbc",输出"acdb",这四个字母的先后顺序遵循输入中的顺序,同时字典序最小。
下面这份代码的大致思路是首先把s中每个字母出现次数统计一次,然后再遍历一次,minLetterIndex保存目前为止出现的字母中字典序最小字母的位置,同时每遇到一个字母,对应的出现次数减一,当减完后次数归0时,就break,也即该字母只在目前这段字符串中出现。break后将s[minLetterIndex]加入结果字符串ret中,s取minLetterIndex + 1(包括)到结尾的一段,同时擦去minLetterIndex对应的字母。在s的长度不为0时一直执行这个操作。
removeLetter函数的思路是保持着s的更新,使[0,k-1]不包括ch,比如输入分别为"aed","e",那么for循环过后s="add",所以擦去k开始(包含k)到结尾的一段。
看懂代码但没明白为什么这么做可以保证输出符合要求,留坑。另外不知道为什么tag是stack,先跟风打一个。
1 class Solution { 2 public: 3 string removeDuplicateLetters(string s) { 4 string ret; 5 vector<int> letterCount; 6 int len = s.length(); 7 int i = 0, minLetterIndex = 0; 8 char ch; 9 10 while (len) 11 { 12 minLetterIndex = 0; 13 letterCount.assign(26, 0); 14 15 for (i = 0; i < len; ++i) 16 ++letterCount[ s[i]-'a' ]; 17 18 for (i = 0; i < len; ++i) 19 { 20 if (s[i] < s[minLetterIndex]) 21 minLetterIndex = i; 22 23 --letterCount[ s[i]-'a' ]; 24 if (letterCount[ s[i]-'a' ] == 0) 25 break; 26 } 27 28 ret += s[minLetterIndex]; 29 ch = s[minLetterIndex]; 30 s = s.substr(minLetterIndex + 1); 31 removeLetter(s, ch); 32 len = s.length(); 33 } 34 35 return ret; 36 } 37 void removeLetter(string &s, char ch) 38 { 39 int len = s.length(), i = 0; 40 int k = 0; 41 42 for (i = 0; i < len; ++i) 43 { 44 if (s[i] != ch) 45 s[k++] = s[i]; 46 } 47 48 s.erase(k, len-k); 49 } 50 };