刷题使我快乐,满脸开心.jpg
- 来源:力扣(LeetCode)
- 链接:https://leetcode.cn/problems/remove-duplicate-letters/
- 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目
给你一个字符串 s
,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小
(要求不能打乱其他字符的相对位置
)。
示例 1:
输入:s = "bcabc"
输出:"abc"
示例 2:
输入:s = "cbacdcbc"
输出:"acdb"
提示:
1 <= s.length <= 104
s
由小写英文字母组成
注意:该题与 1081 https://leetcode-cn.com/problems/smallest-subsequence-of-distinct-characters 相同
思路
这道题跟402
题类似,都可以考虑*单调栈*
的思路,但是不同的是,每个字符有它自己的移除次数,即出现次数减一
;此外就是对于本题中重复出现的字符来说,并非是402
中如果不影响结果大小则可以直接放入结果,留待后续处理的处理方法,而是需要直接移除掉,因为后到的重复的字符,一定会增大结果的字典序大小,这一点可以画图穷举下或者反证一下。
那么到这里,代码结构就比较清晰了,一个是计数、一个是是否已经出现在结果集,其他的条件跟402
没有什么区别了。
代码
func removeDuplicateLetters(s string) string {
sBytes := []byte(s)
byteCountMap := make(map[byte]int, len(s))
hasByteMap := make(map[byte]int, len(s))
for _, sByte := range sBytes {
byteCountMap[sByte]++
hasByteMap[sByte] = 0
}
var tempRes []byte
for _, sByte := range sBytes {
if hasByteMap[sByte] > 0 {
byteCountMap[sByte]--
continue
}
for len(tempRes) > 0 && byteCountMap[tempRes[len(tempRes)-1]] > 1 && sByte < tempRes[len(tempRes)-1] {
byteCountMap[tempRes[len(tempRes)-1]]--
hasByteMap[tempRes[len(tempRes)-1]]--
tempRes = tempRes[:len(tempRes)-1]
}
tempRes = append(tempRes, sByte)
hasByteMap[sByte]++
}
return string(tempRes)
}