输入 输入一行,为一个仅包含字母的字符串。 输出 按照字母出现次数从大到小的顺序输出各个字母和字母次数,用英文分号分隔,注意末尾的分号; 字母和次数间用英文冒号分隔
第一次写的代码,空间复杂度很高,可读性差,但是运行结果没问题。
package main
import (
"fmt"
"sort"
)
func getIndexByValue(list []string, value string) int {
for i, s := range list {
if s == value {
return i
}
}
return -1
}
func main() {
var inputStr string
fmt.Scan(&inputStr)
inputAlphabetList := make([]string, len(inputStr))
alphabets := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
alphabetIndexCount := make([]int, len(alphabets))
for i, v := range inputStr {
inputAlphabetList[i] = string(v)
alphabetIndexCount[getIndexByValue(alphabets, string(v))] = alphabetIndexCount[getIndexByValue(alphabets, string(v))] + 1
}
characterCountList := make([]int, 0)
for _, i := range alphabetIndexCount {
if i > 0 {
notFind := false
for _, i2 := range characterCountList {
if i2 == i {
notFind = true
}
}
if !notFind {
characterCountList = append(characterCountList, i)
}
}
}
//sort.Ints(characterCountList)
sort.Slice(characterCountList, func(i, j int) bool {
return characterCountList[i] > characterCountList[j]
})
groupCharacterListByCount := make([][]string, len(characterCountList))
for i, characterCount := range characterCountList {
for alphabetIndex, alphabetItem := range alphabets {
if characterCount == alphabetIndexCount[alphabetIndex] {
groupCharacterListByCount[i] = append(groupCharacterListByCount[i], alphabetItem)
}
}
}
outputStr := ""
for i, count := range characterCountList {
itemCharacters := groupCharacterListByCount[i]
for _, character := range itemCharacters {
if outputStr == "" {
outputStr = fmt.Sprintf("%s:%d;", character, count)
} else {
outputStr = fmt.Sprintf("%s%s:%d;", outputStr, character, count)
}
}
}
fmt.Println(outputStr)
}
开始思考如何重构:
package main
import (
"fmt"
"sort"
"unicode"
)
type myCharacterCount struct {
Key rune
Count int
}
func main() {
var inputStr string
fmt.Scan(&inputStr)
characterCountMapList := make(map[rune]int)
for _, character := range inputStr {
characterCountMapList[character]++
}
characterCountList := make([]*myCharacterCount, 0)
for s, i := range characterCountMapList {
characterCountList = append(characterCountList, &myCharacterCount{
Key: s,
Count: i,
})
}
// 根据出现次数降序排序,如果次数相同则按字母本身排序(小写在前)
sort.Slice(characterCountList, func(i, j int) bool {
if characterCountList[i].Count != characterCountList[j].Count {
return characterCountList[i].Count > characterCountList[j].Count // 次数降序
} else {
if unicode.IsLower(characterCountList[i].Key) != unicode.IsLower(characterCountList[j].Key) {
return unicode.IsLower(characterCountList[i].Key)
}
return characterCountList[i].Key < characterCountList[j].Key
}
})
outputStr := ""
for _, item := range characterCountList {
if outputStr == "" {
outputStr = fmt.Sprintf("%c:%d;", item.Key, item.Count)
} else {
outputStr = fmt.Sprintf("%s%c:%d;", outputStr, item.Key, item.Count)
}
}
fmt.Println(outputStr)
}
在这里有一个细节开始我没有注意:在golang获取字符的unicode编码时,相同字符的大写<小写(如
- 小写字母
a
的rune
值(97)比大写字母A
的rune
值(65)大。
)。所以做排序时,不能只根据unicode值排序,还要先判断大小写,讲小写字符放到前面