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;
    }
}
目录
相关文章
|
3月前
|
Go
golang力扣leetcode 49.字母异位词分组
golang力扣leetcode 49.字母异位词分组
17 0
|
3月前
|
Go
golang力扣leetcode 17.电话号码的字母组合
golang力扣leetcode 17.电话号码的字母组合
23 0
|
3月前
leetcode-917:仅仅反转字母
leetcode-917:仅仅反转字母
27 0
|
3月前
leetcode-1220:统计元音字母序列的数目
leetcode-1220:统计元音字母序列的数目
30 0
|
3月前
|
Go
golang力扣leetcode 438.找到字符串中所有字母异位词
golang力扣leetcode 438.找到字符串中所有字母异位词
21 0
|
3月前
|
Java C++ Python
leetcode-242:有效的字母异位词
leetcode-242:有效的字母异位词
24 0
|
3月前
|
算法 测试技术 C#
【单调栈】LeetCode2030:含特定字母的最小子序列
【单调栈】LeetCode2030:含特定字母的最小子序列
|
4月前
|
存储 Java
17. 电话号码的字母组合 --力扣 --JAVA
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
29 0
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
|
11天前
【力扣】1832.判断句子是否为全字母句
【力扣】1832.判断句子是否为全字母句