LeetCode每日打卡-316. 去除重复字母

简介: LeetCode每日打卡-316. 去除重复字母19

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

示例 1:

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

示例 2:

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

提示:

1 <= s.length <= 104
s 由小写英文字母组成

思路
要删除已重复的字符,可以在第一次遍历时查询是否重复,而在生成处理后的字符时,需要能快速找到该字符第一次出现的位置,那么可以在第一次遍历时维护一个HashMap<Character,Integer>。
第一次遍历字符串时,若当前遍历的字符不在map中,将该字符和在字符串中的位置存入map中;已存在map中则不作操作。
第二次遍历字符串时,若当前字符在map中,将该字符保留,并且删除该字符的键值对;若不存在,不作操作。这样就可以得到保留第一次出现的字符。
代码


import java.util.*;

class Solution {
    public String removeDuplicateLetters(String s) {
        int len=s.length();
        if(s==null||len<1){
            return "";
        }

        StringBuffer res=new StringBuffer();

        HashMap<Character,Integer> map = new HashMap<Character,Integer>();



        for(int i=0;i<=len-1;i++){
            if(!map.containsKey(s.charAt(i))){
                map.put(s.charAt(i),i);
            }
        }

        for(int i =0;i<=len-1;i++){
            if(map.containsKey(s.charAt(i))){
                res.append(s.charAt(i));
                map.remove(s.charAt(i),i);
            }
        }

        return res.toString();

    }
}

这样做的话就不能保证返回结果的字典序最小;所以我们需要用到栈

输入 "bcabc"
输出 "bca"
预期结果 "abc"

思路

  1. 怎么去重?

用一个vis数组,如果这个字符入栈了,那么我们就把他标记为1,即有这个字符了,当他再出现,我们就不要了,直接跳过;

  1. 为了得到最小的字典序,该怎么做?

当一个s[i]>s[i+1](准确一点应该是栈中前一个数大于后一个数时,类似于单调栈)时,i就可以被弹出去了,但是如果这个s[i]是独苗(后面再没有这个字符了),就不能弹出去了,那么我们用一个num数组存储s中剩余字符的情况,每当我们抛出一个字符或者我们跳过一个数的时候,其数都要减1;


import java.util.Stack;

/**
 * 栈操作 o(n*log(n))
 */
public class Solution {

    public String removeDuplicateLetters(String s) {
        Stack<Character> stack = new Stack<>();


        for (int i = 0; i < s.length(); i++) {
            Character c = s.charAt(i);
            if (stack.contains(c)) {
                continue;
            }

            //public int indexOf(int ch, int fromIndex): 返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。
            while (!stack.isEmpty() && stack.peek() > c && s.indexOf(stack.peek(), i) != -1) {
                stack.pop();
            }
            stack.push(c);
        }
        String rs = "";
        for (int i = 0; i < stack.size(); i++) {
            rs += stack.get(i);
        }
        return rs;
    }
}
目录
相关文章
|
4月前
|
算法 测试技术 C#
【单调栈】LeetCode2030:含特定字母的最小子序列
【单调栈】LeetCode2030:含特定字母的最小子序列
|
1月前
|
存储 算法
LeetCode第49题字母异位词分组
LeetCode第49题"字母异位词分组"的解题方法,通过将每个字符串的字符排序后作为键存储在HashMap中,有效地将所有字母异位词分组。
LeetCode第49题字母异位词分组
|
1月前
|
算法
LeetCode第17题电话号码的字母组合
该文章介绍了 LeetCode 第 17 题电话号码的字母组合的解法,通过分析得出可使用递归和回溯的思想解决,避免循环穷举的高循环次数,并给出了具体的编码实现,同时总结了该题较难理解,需要了解递归的本质,当嵌套循环层次多时可考虑递归。
LeetCode第17题电话号码的字母组合
|
3月前
|
算法 容器
【LeetCode刷题】滑动窗口解决问题:水果成篮、找到字符串中所有字母异位词
【LeetCode刷题】滑动窗口解决问题:水果成篮、找到字符串中所有字母异位词
|
3月前
|
存储 算法 安全
LeetCode 题目 49:字母异位词分组 5种算法实现与典型应用案例【python】
LeetCode 题目 49:字母异位词分组 5种算法实现与典型应用案例【python】
|
3月前
|
存储
力扣经典150题第四十二题:字母异位词分组
力扣经典150题第四十二题:字母异位词分组
19 0
|
3月前
|
存储
力扣经典150题第四十一题:有效的字母异位词
力扣经典150题第四十一题:有效的字母异位词
18 0
|
3月前
|
算法
【经典LeetCode算法题目专栏分类】【第11期】递归问题:字母大小写全排列、括号生成
【经典LeetCode算法题目专栏分类】【第11期】递归问题:字母大小写全排列、括号生成
|
3月前
|
算法
【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串
【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串
|
3月前
|
存储 算法 数据挖掘
leetcode第十七题:解密电话号码的字母组合与应用【python】
leetcode第十七题:解密电话号码的字母组合与应用【python】