2021.8.25 栈:去除重复字母(med)
题目:
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。
需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
注意:该题与 1081 https://leetcode-cn.com/problems/smallest-subsequence-of-
distinct-characters 相同
示例 1:
输入:s = "bcabc"
输出:"abc"
示例 2:
输入:s = "cbacdcbc"
输出:"acdb"
提示:
1 <= s.length <= 10⁴
s 由小写英文字母组成
Related Topics 栈 贪心 字符串 单调栈 👍 586 👎 0
思路:
- 使用一个int数组记录每个字母出现的次数,使用一个boolean数组记录当前字符是否在栈中存在。
- 使用按字符单调递增的栈来储存结果。
- 遍历字符串,每遍历一个字符,int数组对应元素减一,如果该字符对应下标在boolean数组中为true,则证明栈中已有次元素,直接跳过即可。若为false,则判断栈顶元素是否比当前字符大,如果大于,则判断栈顶元素在ch后面还存不存在,如果不存在,则不能将栈顶元素出栈,break;如果存在,则可以出栈,最后将当前字符入栈,boolean字符数组标记该字符已在栈中。循环以上过程即可。
代码:
class Solution {
public String removeDuplicateLetters(String s) {
Deque<Character> stack = new LinkedList<>();
int[] exist = new int[26];
boolean[] isExistInstack = new boolean[26];
for (int i = 0; i < s.length(); i++) {
exist[s.charAt(i)-'a']++;
}
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
//每遍历一个字符,字符数量减一
exist[ch-'a']--;
//证明这个字符已经在栈中存在,直接continue
if (isExistInstack[ch-'a']){
continue;
}else {
//当栈不为空且栈顶元素比这个字符大
while (!stack.isEmpty() && stack.peek()>ch){
//如果ch后面已经没有了栈顶字符,则不pop,直接break
if (exist[stack.peek()-'a']==0){
break;
}
//后面还有,则出栈,且标记次字符已不在栈中
isExistInstack[stack.pop()-'a'] = false;
}
//将当前字符入栈,标记已在栈中
stack.push(ch);
isExistInstack[ch-'a'] = true;
}
}
StringBuilder stringBuilder = new StringBuilder();
while (!stack.isEmpty()){
stringBuilder.append(stack.pop());
}
return stringBuilder.reverse().toString();
}
}