題目:
Given a string which contains only lowercase letters, remove duplicate letters so that every letter appear once and only once. You must make sure your result is the smallest in lexicographical order among all possible results. Example: Given "bcabc" Return "abc" Given "cbacdcbc" Return "acdb"
分析:通過觀察每個字母下標的規律,以"cbacdcbc"為例,
第一步,計算下標(countIndex):
a => 2, b => 1, 6 c => 0, 3, 5, 7 d => 4
第二步,尋找符合條件的字母(findLetter):
如果一個字母的第一個下標小於其后每個字母的最后一個下標,則該字母符合條件。比如 a 中的 2 小於 b 的 6,c 的 7,d 的 4,則 a 中的2符合條件。
第三步,刪除前面的下標(removeIndex):
不防設第二步中符合條件的字母為X,則刪除X下標之前的所有下標,並刪除X。比如X為a,X下標為2,則刪除 b 中的 1,c 中的 0,並把 a 刪除。
重復第二步,第三步,直到集合為空。
以 "cbacdcbc" 為例:
b => 6 c => 3, 5, 7 d => 4
b => 6
d => 4
上述變換解釋:雖然 6 < 7,但 6 卻 > 4, 故 b 不符合,而 c 中的 3 小於其后的 4,故 c 符合。
b => 6
故最后生成 a -> c -> d -> b,即 acdb.
代碼如下:
public String removeDuplicateLetters(String s) { StringBuilder res = new StringBuilder(); HashMap<Character, ArrayList<Integer>> hm = new HashMap<Character, ArrayList<Integer>>(); ArrayList<Character> reference = new ArrayList<Character>(); countIndex(s, hm, reference); Collections.sort(reference); while (!reference.isEmpty()) { int lettIndex = findLetter(s, res, hm, reference); removeIndex(lettIndex, hm, reference); } return res.toString(); } private void countIndex(String s, HashMap<Character, ArrayList<Integer>> hm, ArrayList<Character> reference) { for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (! hm.containsKey(ch)) { ArrayList<Integer> tmp = new ArrayList<Integer>(); tmp.add(i); hm.put(ch, tmp); reference.add(ch); } else { hm.get(ch).add(i); } } } private int findLetter(String s, StringBuilder res, HashMap<Character, ArrayList<Integer>> hm, ArrayList<Character> reference) { int m = 0; for (int i = 0; i < reference.size(); i++) { m = hm.get(reference.get(i)).get(0); int j = i+1; for (; j < reference.size(); j++) { ArrayList<Integer> tmp = hm.get(reference.get(j)); if (m > tmp.get(tmp.size()-1)) { break; } } if (j == reference.size()) { res.append(reference.get(i)); reference.remove(i); break; } } return m; } private void removeIndex(int lett, HashMap<Character, ArrayList<Integer>> hm, ArrayList<Character> reference) { for (int i = 0; i < reference.size(); i++) { ArrayList<Integer> tmp = hm.get(reference.get(i)); while (!tmp.isEmpty() && tmp.get(0) < lett) { tmp.remove(0); } } }
