【LeetCode】316.去除重复字母
题目链接
316. 去除重复字母
题目描述
解题思路
单调栈的应用
本题的解决可以分为两个过程:
(1) 去重,使得所有元素只出现一次。
(2) 返回字典序最小
先忽略过程2,利用栈这个数据结构实现去重。去重的原理就是利用isUsed数组标记该元素是否在栈中出现,如果是则跳过,否则在栈中加入该元素。
如何让栈中存在的字符串组成的字典序最小呢?
这就是单调栈的应用,但是必须要注意的一点就是:当栈顶元素大于要push进去的元素时
stk.peek() > c 时才会 pop 元素,其实这时候应该分两种情况:
-
如果 st.peek() 这个字符之后还会出现,那么可以把它 pop 出去,反正后面还有嘛,后面再 push 到栈里,刚好符合字典序的要求。
-
如果 st.peek() 这个字符之后不会出现了,前面也说了栈中不会存在重复的元素,那么就不能把它 pop 出去,否则你就永远失去了这个字符。
AC代码
//1.利用栈实现去重
class Solution {
public String removeDuplicateLetters(String s) {
Stack<Character> st = new Stack();
StringBuffer ans = new StringBuffer();
boolean isUsed[] = new boolean[26];
char[] sChar = s.toCharArray();
int charCount[] = new int[26];
for(char i : sChar){
if(isUsed[i-'a']) continue;
st.push(i);
isUsed[i-'a'] = true;
}
while(!st.isEmpty()) ans.append(st.pop());
return ans.reverse().toString();
}
}
//2.完整代码
class Solution {
public String removeDuplicateLetters(String s) {
Stack<Character> st = new Stack();
StringBuffer ans = new StringBuffer();
//根据isUsed数组实现栈中元素去重
boolean isUsed[] = new boolean[26];
char[] sChar = s.toCharArray();
int charCount[] = new int[26];
//记录每个字符出现的次数
for(char i : sChar) charCount[i-'a']++;
for(char i : sChar){
charCount[i-'a']--;
if(isUsed[i-'a']) continue;
while(!st.isEmpty() && st.peek() > i && charCount[st.peek()-'a'] > 0){
isUsed[st.peek()-'a'] = false;
st.pop();
}
st.push(i);
isUsed[i-'a'] = true;
}
while(!st.isEmpty()) ans.append(st.pop());
return ans.reverse().toString();
}
}