当前位置 博文首页 > Inmaturity_7的博客:算法练习帖--34--去除重复字母(Java)

    Inmaturity_7的博客:算法练习帖--34--去除重复字母(Java)

    作者:[db:作者] 时间:2021-08-01 11:43

    去除重复字母

    一、题目简介

    给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
    (题目来源:力扣(LeetCode))

    示例 1:
    输入:s = "bcabc"
    输出:"abc"
    
    示例 2:
    输入:s = "cbacdcbc"
    输出:"acdb"
    
    提示:
    1 <= s.length <= 104
    s 由小写英文字母组成
    
    

    二、解决方法

    1. 三部曲:超详细的步骤介绍
    class Solution {
        public String removeDuplicateLetters(String s) {
        Stack<Character> stk = new Stack<>();
    
        // 维护一个计数器记录字符串中字符的数量
        // 因为输入为 ASCII 字符,大小 256 够用了
        int[] count = new int[256];
        for (int i = 0; i < s.length(); i++) {
            count[s.charAt(i)]++;
        }
    
        boolean[] inStack = new boolean[256];
        for (char c : s.toCharArray()) {
            // 每遍历过一个字符,都将对应的计数减一
            count[c]--;
    
            if (inStack[c]) continue;
    
            while (!stk.isEmpty() && stk.peek() > c) {
                // 若之后不存在栈顶元素了,则停止 pop
                if (count[stk.peek()] == 0) {
                    break;
                }
                // 若之后还有,则可以 pop
                inStack[stk.pop()] = false;
            }
            stk.push(c);
            inStack[c] = true;
        }
    
        StringBuilder sb = new StringBuilder();
        while (!stk.empty()) {
            sb.append(stk.pop());
        }
        return sb.reverse().toString();
    }
    }
    
    1. 贪心加栈(官方题解,思想和题解1一样,但是较为优化)
    class Solution {
        public String removeDuplicateLetters(String s) {
            boolean[] vis = new boolean[26];
            int[] num = new int[26];
            for (int i = 0; i < s.length(); i++) {
                num[s.charAt(i) - 'a']++;
            }
    
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < s.length(); i++) {
                char ch = s.charAt(i);
                if (!vis[ch - 'a']) {
                    while (sb.length() > 0 && sb.charAt(sb.length() - 1) > ch) {
                        if (num[sb.charAt(sb.length() - 1) - 'a'] > 0) {
                            vis[sb.charAt(sb.length() - 1) - 'a'] = false;
                            sb.deleteCharAt(sb.length() - 1);
                        } else {
                            break;
                        }
                    }
                    vis[ch - 'a'] = true;
                    sb.append(ch);
                }
                num[ch - 'a'] -= 1;
            }
            return sb.toString();
        }
    }
    
    
    cs