2020-01-19 13:18:11
问题描述:
问题求解:
本题是要求挑选出一个字符串的子序列,并且保证得到的子序列中能够有所有出现的字符且其字典序最小。
最容易想到的解法就是dfs了,暴力去进行检索,并生成所有的满足条件的子序列,最后从中得到字典序最小的那个。可惜使用这种算法的结果是tle。
第二个思路是用map将所有的idx保存下来,之后进行二分检索,但是这个时间复杂度也非常高。
最优的解法是使用count数组和visited数组来对字符进行统计,如果当前的字符已经出现过,那么直接pass,因为越前出现越好;如果当前的字符并没有出现,并且前面的字符比他大,而且其count大于0,那么前面的字符就可以弹出。
public String removeDuplicateLetters(String s) { int[] seen = new int[26]; char[] chs = s.toCharArray(); int n = chs.length; for (char c : chs) seen[c - 'a'] += 1; Stack<Character> stack = new Stack<>(); HashSet<Character> used = new HashSet<>(); for (char c : chs) { seen[c - 'a'] -= 1; if (used.contains(c)) continue; while (!stack.isEmpty() && c < stack.peek() && seen[stack.peek() - 'a'] > 0) { char tmp = stack.pop(); used.remove(tmp); } stack.push(c); used.add(c); } StringBuffer sb = new StringBuffer(); while (!stack.isEmpty()) sb.append(stack.pop()); return sb.reverse().toString(); }