[LeetCode 316. 去除重复字母] | 刷题打卡

81 阅读1分钟

一、题目描述:

leetcode-cn.com/problems/re…

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

****示例 1:

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

二、思路分析:

  • 先扫描一次字符串记录,字符出现的次数
  • 然后使用单调栈,保证栈中的字符按字典序排序,这时又分为两种情况(如果是已经出现在栈中的字符,则直接跳过就好,因为要保证字符串中的字符不重复):
    • 1.如果字符的次数大于1,那么可以把它 pop 出去,后面再 push 到栈里,刚好符合字典序的要求(仔细思考一下,若果后面还会出现这个字符,且当前扫描到的字符已经小于栈顶的元素了,那么结果序列必不包含当前栈顶的字符)
    • 2.如果字符出现的次数等于1,前面也说了栈中不会存在重复的元素,那么就不能把它 pop 出去

三、AC 代码:

/**
 * @param {string} s
 * @return {string}
 */
var removeDuplicateLetters = function (s) {
    const counterMap = {}
    for (let i = 0; i < s.length; i++) {
        if (!counterMap[s[i]]) {
            counterMap[s[i]] = 1
        } else {
            counterMap[s[i]]++
        }
    }

    const inStackMap = {}

    const stack = []

    for (let i = 0; i < s.length; i++) {
        counterMap[s[i]]--

        if (inStackMap[s[i]]) {
            continue
        }
        while (s[i] < stack[stack.length - 1]) {
            if (counterMap[stack[stack.length-1]] === 0) {
                break
            }
            let popEle = stack.pop()
            inStackMap[popEle] = false
        }
        stack.push(s[i])
        inStackMap[s[i]] = true
    }
    return stack.join("")
};

四、总结:

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情