【LeetCode】316.去除重複字母
阿新 • • 發佈:2020-12-20
題目連結
316. 去除重複字母
題目描述
解題思路
單調棧的應用
本題的解決可以分為兩個過程:
(1) 去重,使得所有元素只出現一次。
(2) 返回字典序最小
先忽略過程2,利用棧這個資料結構實現去重。去重的原理就是利用isUsed陣列標記該元素是否在棧中出現,如果是則跳過,否則在棧中加入該元素。
如何讓棧中存在的字串組成的字典序最小呢?
這就是單調棧的應用,但是必須要注意的一點就是:當棧頂元素大於要push進去的元素時
stk.peek() > c 時才會 pop 元素,其實這時候應該分兩種情況:
-
如果 st.peek() 這個字元之後還會出現,那麼可以把它 pop 出去,反正後面還有嘛,後面再 push 到棧裡,剛好符合字典序的要求。
-
如果 st.peek() 這個字元之後不會出現了,前面也說了棧中不會存在重複的元素,那麼就不能把它 pop 出去,否則你就永遠失去了這個字元。
AC程式碼
//1.利用棧實現去重 class Solution { public String removeDuplicateLetters(String s) { Stack<Character> st = new Stack(); StringBuffer ans = new StringBuffer(); boolean isUsed[] = new boolean[26]; char[] sChar = s.toCharArray(); int charCount[] = new int[26]; for(char i : sChar){ if(isUsed[i-'a']) continue; st.push(i); isUsed[i-'a'] = true; } while(!st.isEmpty()) ans.append(st.pop()); return ans.reverse().toString(); } } //2.完整程式碼 class Solution { public String removeDuplicateLetters(String s) { Stack<Character> st = new Stack(); StringBuffer ans = new StringBuffer(); //根據isUsed陣列實現棧中元素去重 boolean isUsed[] = new boolean[26]; char[] sChar = s.toCharArray(); int charCount[] = new int[26]; //記錄每個字元出現的次數 for(char i : sChar) charCount[i-'a']++; for(char i : sChar){ charCount[i-'a']--; if(isUsed[i-'a']) continue; while(!st.isEmpty() && st.peek() > i && charCount[st.peek()-'a'] > 0){ isUsed[st.peek()-'a'] = false; st.pop(); } st.push(i); isUsed[i-'a'] = true; } while(!st.isEmpty()) ans.append(st.pop()); return ans.reverse().toString(); } }