力扣316. 去除重复字母

力扣316

题目描述

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
字符串都由小写字母组成。

题目分析

  1. 需要维护一个字符串对应的Hash频数数组freq,用来存储每个元素所出现的次数。数组的下标 =字符-‘a’,表示该字母所对应的数值,存储的元素表示该字母在字符串中总共出现的次数。eg:s = abccaa, freq[a-‘a’] = 3;
  2. 为保证字典序尽量最小,我们可以维护一个栈。尽量单调递增栈。这样的话,出栈之后将其反序就是最小的了。如果栈顶元素 > 待入栈元素,且栈顶元素在后续中还有,就将栈顶元素出栈。
  3. 如果栈中已经存在了的元素,再次访问到的话就不需要入栈了,那么就需要维护一个集合set,利用set的不可重复性。
  4. 最后有一个点需要注意(不是太懂!!再看),是提交时一个例子不对发现的abca。因为当走到最后一个a时,前面的在栈中都是有序的,并且a已经在 集合中有了(即栈中有了),就不将该节点a入栈了。栈中也不动。

示例 1:
输入:s = “bcabc”
输出:“abc”
示例 2:
输入:s = “cbacdcbc”
输出:“acdb”
最后特例: s=“abca”
输出:“abc”

class Solution {
    public String removeDuplicateLetters(String s) {
        
//先维护一个字符串对应的Hash频数数组,用来存储每个元素在字符串中出现的次数(这个在后续有大用处)
        int[] freq = new int[26];
        char[] charArrays = s.toCharArray();//将字符串变为字符数组
//维护一个 尽量单调递增栈(即后序还有该字母的情况下让其大的在上边,若后序没有该字母了就只能按字符串中顺序了),最后出栈之后反序一下就是从小到大(尽量)。
        Stack<Character> stack = new Stack<>();
        Set<Character> set = new HashSet<>();
        for(char ch : charArrays){
            freq[ch - 'a']++;
        }
//定义一个字符串构造器StringBuilder
        StringBuilder sb = new StringBuilder();

        //尽量单调递增栈(这是理解此题的最关键字眼),
        for(char ch : charArrays){
            while(!stack.isEmpty() && stack.peek() >= ch && freq[stack.peek()-'a'] > 0 && !set.contains(ch)){
                //如果栈顶元素 >= 让栈顶出栈,且该栈顶元素在后续中还有,则让该栈顶元素出栈且移除集合
                set.remove(stack.peek());
                stack.pop();
            }
            //被访问过的字符频数-1;
            freq[ch - 'a']--;
        //集合set就是为了看字符是否在栈中已经出现了,若出现了就直接跳过不再处理
            if(set.contains(ch)) continue;
            set.add(ch);
            stack.push(ch); 
        }

        //把栈中的字符挨个添加到字符构造器sb之后,然后再将sb反序即可得结果
        while(!stack.isEmpty()){
            sb.append(stack.pop());
        }
        sb.reverse();
        return sb.toString();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值