LeetCode 去除重复字母

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

思路:

  1. 使用一个int数组记录每个字母出现的次数,使用一个boolean数组记录当前字符是否在栈中存在。
  2. 使用按字符单调递增的栈来储存结果。
  3. 遍历字符串,每遍历一个字符,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();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值