2021-08-31:去除重复字母。给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。力扣316。
Posted 福大大架构师每日一题
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-08-31:去除重复字母。给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。力扣316。相关的知识,希望对你有一定的参考价值。
2021-08-31:去除重复字母。给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。力扣316。
福大大 答案2021-08-31:
k种字符。
时间复杂度:O(k*N)。
空间复杂度:O(k)。
代码用golang编写。代码如下:
package main
import (
"fmt"
"strings"
)
func main() {
str := "abcdea"
ret := removeDuplicateLetters1(str)
fmt.Println(ret)
ret = removeDuplicateLetters2(str)
fmt.Println(ret)
}
// 在str中,每种字符都要保留一个,让最后的结果,字典序最小 ,并返回
func removeDuplicateLetters1(str string) string {
if len(str) < 2 {
return str
}
map0 := make([]int, 256)
for i := 0; i < len(str); i++ {
map0[str[i]]++
}
minACSIndex := 0
for i := 0; i < len(str); i++ {
if str[minACSIndex] > str[i] {
minACSIndex = i
}
map0[str[i]]--
if map0[str[i]] == 0 {
break
}
}
// 0...break(之前) minACSIndex
// str[minACSIndex] 剩下的字符串str[minACSIndex+1...] -> 去掉str[minACSIndex]字符 -> s'
// s'...
return fmt.Sprintf("%c", str[minACSIndex]) + strings.ReplaceAll(str[minACSIndex+1:], fmt.Sprintf("%c", str[minACSIndex]), "")
}
func removeDuplicateLetters2(s string) string {
// 小写字母ascii码值范围[97~122],所以用长度为26的数组做次数统计
// 如果map[i] > -1,则代表ascii码值为i的字符的出现次数
// 如果map[i] == -1,则代表ascii码值为i的字符不再考虑
map0 := make([]int, 26)
for i := 0; i < len(s); i++ {
map0[s[i]-'a']++
}
res := make([]byte, 26)
index := 0
L := 0
R := 0
for R != len(s) {
// 如果当前字符是不再考虑的,直接跳过
// 如果当前字符的出现次数减1之后,后面还能出现,直接跳过
ok := false
if !ok {
ok = map0[s[R]-'a'] == -1
}
if !ok {
map0[s[R]-'a']--
ok = map0[s[R]-'a'] > 0
}
if ok {
R++
} else { // 当前字符需要考虑并且之后不会再出现了
// 在str[L..R]上所有需要考虑的字符中,找到ascii码最小字符的位置
pick := -1
for i := L; i <= R; i++ {
if map0[s[i]-'a'] != -1 && (pick == -1 || s[i] < s[pick]) {
pick = i
}
}
// 把ascii码最小的字符放到挑选结果中
res[index] = s[pick]
index++
// 在上一个的for循环中,str[L..R]范围上每种字符的出现次数都减少了
// 需要把str[pick + 1..R]上每种字符的出现次数加回来
for i := pick + 1; i <= R; i++ {
if map0[s[i]-'a'] != -1 { // 只增加以后需要考虑字符的次数
map0[s[i]-'a']++
}
}
// 选出的ascii码最小的字符,以后不再考虑了
map0[s[pick]-'a'] = -1
// 继续在str[pick + 1......]上重复这个过程
L = pick + 1
R = L
}
}
return string(res[0:index])
}
执行结果如下:
以上是关于2021-08-31:去除重复字母。给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。力扣316。的主要内容,如果未能解决你的问题,请参考以下文章