zoukankan      html  css  js  c++  java
  • Leetcode316.去除重复字母

    316. 去除重复字母

    Difficulty: 中等

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

    注意:该题与 1081 相同

    示例 1:

    输入:s = "bcabc"
    输出:"abc"
    

    示例 2:

    输入:s = "cbacdcbc"
    输出:"acdb"
    

    提示:

    • 1 <= s.length <= 10<sup>4</sup>
    • s 由小写英文字母组成

    Solution

    思路:栈的使用。官方题解(视频思路很清楚)
    字符串如何判断字典序大小呢,先比较字符串首字符在字典出现的次序,越早出现,字符串字典序越小,如果一样,那么就比较下一个字符的出现次序。
    针对此题,因为字符长度最为(10^4),因此,最好只遍历一遍字符串,否则时间将会超时。那么遍历字符串时,先设置一个存放最终结果的list,当遍历到第i个字符时,

    • step1:那么判断第i-1个字符是否在位置i之后还会出现:
    • step1.1: 如果不会出现,那么就无法改变字典序,只能将第i个字符加入list中;
    • step1.2:如果会出现,那么要判断在后面出现时的字典序会不会比在第i-1位置出现的字典序来得小:
    • step1.2.1:如果会的话,那么要删去第i-1个字符,然后在重新回到step1;
    • step1.2.2:如果不会的话,那么就保留第i-1位置的字符,之后出现的与第i-1字符相同的都不能再使用,因为他们构成的字符串字典序一定更大。

    上面可能讲的有点乱,当应该可以发现存放结果的list每次增删都是在队尾操作,这很符合栈。

    Language: java

    
    class Solution {
        public String removeDuplicateLetters(String s) {
            char[] arr = s.toCharArray();
            int[] num = new int[26];
            for(char c : arr){
                num[c - 'a'] ++;//记录重复的个数
            }
            Deque<Character> stack = new ArrayDeque<>();
            int[] vis = new int[26];
            for(char c : arr){
                if(vis[c - 'a'] == 1) {
                    num[c - 'a'] --;//当前字符被访问过了,不再访问
                    continue;
                }
                if(stack.isEmpty() || stack.peek() < c){//当前字符比前一个栈顶字符来得大,符合较小字典序的规律,直接入栈
                    stack.push(c);
                    vis[c - 'a'] = 1;
                    num[c - 'a'] --;
                }else{
                    while(!stack.isEmpty() && stack.peek() > c && num[stack.peek() - 'a'] > 0){//当前字符比栈顶大,同时,栈顶字符在后面字符串中还会出现,那么就出栈
                        vis[stack.pop() - 'a'] = 0;
                    }
                    stack.push(c);
                    vis[c - 'a'] = 1;
                    num[c - 'a'] --;
                }
            }
            StringBuilder sb = new StringBuilder();
            while(!stack.isEmpty()){
                sb.append(stack.pollLast());
            }
            return sb.toString();
        }
    }
    
    
  • 相关阅读:
    设计模式之迭代器与组合模式(三)
    设计模式之迭代器与组合模式(二)
    设计模式之迭代器与组合模式(一)
    设计模式之模板方法模式(一)
    设计模式之模板方法模式(三)
    设计模式之模板方法模式(二)
    Spring Cloud微服务初探
    设计模式之适配器模式与外观模式(二)
    设计模式之适配器模式与外观模式(一)
    设计模式之命令模式(三)
  • 原文地址:https://www.cnblogs.com/liuyongyu/p/14164318.html
Copyright © 2011-2022 走看看