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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class24;
// 本题重写了
// 不用看课上的解释了
// 这道题最优解是单调栈的解法
// 看注释能看懂
// 本题测试链接 : https://leetcode.com/problems/remove-duplicate-letters/
public class Code06_RemoveDuplicateLettersLessLexi {
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']++;
}
// 单调栈
// 从左到右只保留依次变大的字符
// 比如: 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--;
}
// 当前字符进入了单调栈
stack[size++] = cur;
}
// 当前字符的词频调整,调整后表示后面还有多少个当前字符
// 注意词频表更新
cnts[cur - 'a']--;
}
// 单调栈里的字符,拼字符串返回
return String.valueOf(stack, 0, size);
}
}