You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
2.2 KiB

2 years ago
package class24;
2 years ago
// 本题重写了
// 不用看课上的解释了
// 这道题最优解是单调栈的解法
// 看注释能看懂
2 years ago
// 本题测试链接 : https://leetcode.com/problems/remove-duplicate-letters/
public class Code06_RemoveDuplicateLettersLessLexi {
2 years ago
public static String removeDuplicateLetters(String s) {
int[] cnts = new int[26];
boolean[] enter = new boolean[26];
for (int i = 0; i < s.length(); i++) {
cnts[s.charAt(i) - 'a']++;
2 years ago
}
2 years ago
// 单调栈
// 从左到右只保留依次变大的字符
// 比如: a c e....
char[] stack = new char[26];
int size = 0;
for (int i = 0; i < s.length(); i++) {
// 假设当前字符是d
char cur = s.charAt(i);
// 如果d已经在单调栈里不进入!
// 因为单调栈里每种字符只保留一个
if (!enter[cur - 'a']) {
// 如果d不在单调栈里进入!
enter[cur - 'a'] = true;
// 如果单调栈里已经有 :
// a c e f
// 当前字符是d
// 那么f弹出、e弹出、然后d进入
// 单调栈变成 : a c d
// 但是!
// 如果后面还有ff才能弹出
// 如果后面还有ee才能弹出
// 如果一个字符要弹出,但是后面已经没有这种字符了,不能弹出!
// 因为一旦弹出,再也没有机会收集到这种字符了!因为后面没有了
// 这就是核心逻辑
// 所以 : size > 0表示单调栈里有字符
// stack[size - 1] > cur表示单调栈当前最右的字符比当前字符大那么它弹出
// cnts[stack[size - 1] - 'a'] > 0重要限制 : 后面还有单调栈当前最右的字符,才能弹出
// 缺一不可
while (size > 0 && stack[size - 1] > cur && cnts[stack[size - 1] - 'a'] > 0) {
// 这种字符要弹出了,所以标记这种字符出去了
enter[stack[size - 1] - 'a'] = false;
// 单调栈大小缩减了,也就是弹出了
size--;
2 years ago
}
2 years ago
// 当前字符进入了单调栈
stack[size++] = cur;
2 years ago
}
2 years ago
// 当前字符的词频调整,调整后表示后面还有多少个当前字符
// 注意词频表更新
cnts[cur - 'a']--;
2 years ago
}
2 years ago
// 单调栈里的字符,拼字符串返回
return String.valueOf(stack, 0, size);
2 years ago
}
}