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.

75 lines
2.6 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 {
// 在str中每种字符都要保留一个让最后的结果字典序最小 ,并返回
public static String removeDuplicateLetters1(String str) {
if (str == null || str.length() < 2) {
return str;
}
int[] map = new int[256];
for (int i = 0; i < str.length(); i++) {
map[str.charAt(i)]++;
}
int minACSIndex = 0;
for (int i = 0; i < str.length(); i++) {
minACSIndex = str.charAt(minACSIndex) > str.charAt(i) ? i : minACSIndex;
if (--map[str.charAt(i)] == 0) {
break;
}
}
// 0...break(之前) minACSIndex
// str[minACSIndex] 剩下的字符串str[minACSIndex+1...] -> 去掉str[minACSIndex]字符 -> s'
// s'...
return String.valueOf(str.charAt(minACSIndex)) + removeDuplicateLetters1(
str.substring(minACSIndex + 1).replaceAll(String.valueOf(str.charAt(minACSIndex)), ""));
}
public static String removeDuplicateLetters2(String s) {
char[] str = s.toCharArray();
// 小写字母ascii码值范围[97~122]所以用长度为26的数组做次数统计
// 如果map[i] > -1则代表ascii码值为i的字符的出现次数
// 如果map[i] == -1则代表ascii码值为i的字符不再考虑
int[] map = new int[26];
for (int i = 0; i < str.length; i++) {
map[str[i] - 'a']++;
}
char[] res = new char[26];
int index = 0;
int L = 0;
int R = 0;
while (R != str.length) {
// 如果当前字符是不再考虑的,直接跳过
// 如果当前字符的出现次数减1之后后面还能出现直接跳过
if (map[str[R] - 'a'] == -1 || --map[str[R] - 'a'] > 0) {
R++;
} else { // 当前字符需要考虑并且之后不会再出现了
// 在str[L..R]上所有需要考虑的字符中找到ascii码最小字符的位置
int pick = -1;
for (int i = L; i <= R; i++) {
if (map[str[i] - 'a'] != -1 && (pick == -1 || str[i] < str[pick])) {
pick = i;
}
}
// 把ascii码最小的字符放到挑选结果中
res[index++] = str[pick];
// 在上一个的for循环中str[L..R]范围上每种字符的出现次数都减少了
// 需要把str[pick + 1..R]上每种字符的出现次数加回来
for (int i = pick + 1; i <= R; i++) {
if (map[str[i] - 'a'] != -1) { // 只增加以后需要考虑字符的次数
map[str[i] - 'a']++;
}
}
// 选出的ascii码最小的字符以后不再考虑了
map[str[pick] - 'a'] = -1;
// 继续在str[pick + 1......]上重复这个过程
L = pick + 1;
R = L;
}
}
return String.valueOf(res, 0, index);
}
}