给你一个字符串 s
,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
示例 1:
输入:s = "bcabc"
输出:"abc"
输入:s = "cbacdcbc"
输出:"acdb"
参考: 力扣
需要用到栈的数据结构
vis记录栈内是否有该字母,num记录字母最后出现的下标
遍历所有字母
- 如果栈内已有该字母跳过不加入
- 比较栈顶字母,如果栈顶字母比现在字母大且栈顶字母后续还有(最后位置比当前位置靠后)说明可以删去当前栈顶字母(因为后续可以加入)
- 加入当前字母
注意:加入删除字母的时候应该两个数组全部删除。
class Solution {
public String removeDuplicateLetters(String s) {
boolean[] vis = new boolean[26];// 表明栈中是否有该元素
int[] num = new int[26];// 记录每个字母最后出现的下标
char[] cs = s.toCharArray();
int l = cs.length;
for (int i = 0; i < l; i++) {
num[cs[i] - 'a'] = i;
}
// 用StringBuffer当栈,也可用deque
StringBuffer sb = new StringBuffer();
for (int i = 0; i < l; i++) {
// 遍历s
char ch = cs[i];
// 栈中有该字母直接跳过不需要计算
if(vis[ch-'a']){
continue;
}
// 栈顶最后的字符比当前字符大 且 后续有栈顶最后的字符
// 此时就可以去除当前栈顶最后的字符
// 去除注意需要把vis和sb都去除
while (sb.length() > 0 && sb.charAt(sb.length() - 1) > ch && num[sb.charAt(sb.length() - 1) - 'a'] > i) {
vis[sb.charAt(sb.length() - 1) - 'a'] = false;
sb.deleteCharAt(sb.length() - 1);
}
// 加入当前字符
vis[ch - 'a'] = true;
sb.append(ch);
}
// 返回sb即可
return sb.toString();
}
}