输入 输入一行,为一个仅包含字母的字符串。 输出 按照字母出现次数从大到小的顺序输出各个字母和字母次数,用英文分号分隔,注意末尾的分号; 字母和次数间用英文冒号分隔
第一次写的代码,空间复杂度很高,可读性差,但是运行结果没问题。
package mainimport ("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 stringfmt.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 := falsefor _, 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 mainimport ("fmt""sort""unicode"
)type myCharacterCount struct {Key runeCount int
}func main() {var inputStr stringfmt.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值排序,还要先判断大小写,讲小写字符放到前面