import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @return string字符串
*/
public String removeDuplicateLetters (String str) {
// 如果栈为空,元素进栈
// 如果当前元素比栈顶元素字典序大,当前元素入栈
// 如果当前元素比栈顶元素字典序小,且后续还会出现栈顶元素,则将栈顶元素弹出
// 如果当前元素比栈顶元素字典序小,且后续不会会出现栈顶元素,则不能将栈顶元素弹出
// 如果当前元素已经存在于栈中,则忽略该元素
int len = str.length();
char[] chars = str.toCharArray();
//记录每个字符出现的最后一个位置
int[] lastIndex = new int[26];
for (int i = 0; i < len; i++) {
lastIndex[chars[i] - 'a'] = i;
}
//栈保存字典序最小的字符串
Deque<Character> stack = new ArrayDeque<>(len);
//保存栈中持有的字符
boolean[] visited = new boolean[26];
for (int i = 0; i < len; i++) {
char currentCh = chars[i];
//如果栈中存在当前字符,则忽略
if (visited[currentCh - 'a']) {
continue;
}
//如果栈不空,并且当前元素比栈顶元素字典序小,并且后续存在栈顶元素
//则将栈顶元素弹出,同时标记栈中不存在此元素
while (!stack.isEmpty() && currentCh < stack.peekLast()
&& lastIndex[stack.peekLast() - 'a'] > i) {
Character top = stack.removeLast();
visited[top - 'a'] = false;
}
//其他情况入栈,将当前元素标记为存在栈中。
stack.addLast(currentCh);
visited[currentCh - 'a'] = true;
}
StringBuilder sb = new StringBuilder();
for (Character ch : stack) {
sb.append(ch);
}
return sb.toString();
}
}