316. 去除重复字母
1081. 不同字符的最小子序列
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
注意:该题与 1081 https://leetcode-cn.com/problems/smallest-subsequence-of-distinct-characters 相同
示例 1:
输入:s = "bcabc"
输出:"abc"
示例 2:
输入:s = "cbacdcbc"
输出:"acdb"
运行结果
解题思路
利用栈记录结果
去重的入栈:已入栈跳过。当出现栈顶元素大于当前元素时判断,如果后续还有则出栈,后续再入,否则跳过
所以需要辅助数组来记录是否已经入栈,以及后续还有几个
26的数组是存字母到a的距离
256是直接存字母的ascll码
时间换空间
java代码
class Solution {
public String removeDuplicateLetters(String s) {
int[] count=new int[26];//记录字符数目-26个英文字母
boolean[] inStack=new boolean[26];//记录是否入栈
Stack<Character> stack=new Stack<>();
char[] chars=s.toCharArray();
//记录字母的数目
for(char c:chars){
count[c-'a']++;
}
for(char c : chars){
//数目减一
count[c-'a']--;
//已有则去重
if(inStack[c-'a']) continue;
//栈顶较小时
while( !stack.isEmpty() && stack.peek() > c){
//后续没有则跳出。必须有,不然会死循环
if(count[stack.peek() - 'a']==0) break;
//后续还有则弹出
inStack[stack.pop()-'a']=false;
}
//入栈,改标志位
stack.push(c);
inStack[c-'a']=true;
}
//记录结果集
StringBuffer sb=new StringBuffer();
while(!stack.isEmpty()){
sb.append(stack.pop());
}
return sb.reverse().toString();
}
}class Solution {
public String smallestSubsequence(String s) {
int[] count=new int[256];
boolean[] instack=new boolean[256];
Stack<Character> stk=new Stack<>();
char[] chars=s.toCharArray();
//记录字母的数目
for(char c: chars){
count[c]++;
}
for(char c : chars){
//遍历减1
count[c]--;
//已入栈去重
if(instack[c]) continue;
//若栈顶过大
while( !stk.isEmpty() && stk.peek() > c){
//若后续没有则跳过
if(count[stk.peek()]==0) break;
//否则出栈,改标志
instack[stk.pop()]=false;
}
//入栈改标志
stk.push(c);
instack[c]=true;
}
//记录结果
StringBuilder sb=new StringBuilder();
while(!stk.isEmpty()){
sb.append(stk.pop());
}
return sb.reverse().toString();
}
}
京公网安备 11010502036488号