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"
Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
思路:单调递增栈保证了lexicographical order是最小的;为了保证字母顺序是最小的。那么也就是说,如果先遇见的字母,后面还有,而且比我当前的要靠后,那么pop之前的,先放我现在的。比如说bab, 先遇见b了,再遇见a,那么我看b后面还有,那么对不起,pop b,我后面再加上你。用stack来保存信息,并保存stack的信息永远是递增的,首先count一下字母的频率,遇见一个char,就把频率降低-1,如果当前遇见的char,已经被visit过了,那么直接跳过,如果没有,那么check count里面还有没有,没有就不pop,有的话,那么就pop,因为后面还有不要着急。然后最后再把stack里面的char组合起来,反向输送。
class Solution {
public String removeDuplicateLetters(String s) {
if(s == null || s.length() == 0) {
return s;
}
Stack<Character> stack = new Stack<>();
int count[] = new int[26];
boolean[] visited = new boolean[26];
for(int i = 0; i < s.length(); i++) {
count[s.charAt(i) - 'a']++;
}
// bab, 遇见a, pop第一个b,因为后面还有;
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
count[c - 'a']--;
if(visited[c - 'a']) {
continue;
}
// 如果当前的比c要大,而且后面还有,那么pop当前的;visited记住标记为false;
while(!stack.isEmpty() && stack.peek() > c && count[stack.peek() - 'a'] > 0) {
visited[stack.peek() - 'a'] = false;
stack.pop();
}
visited[c - 'a'] = true;
stack.push(c);
}
StringBuilder sb = new StringBuilder();
while(!stack.isEmpty()) {
sb.insert(0, stack.pop());
}
return sb.toString();
}
}