【华为OD机试真题】4、字符统计及重排

输入 输入一行,为一个仅包含字母的字符串。  输出 按照字母出现次数从大到小的顺序输出各个字母和字母次数,用英文分号分隔,注意末尾的分号; 字母和次数间用英文冒号分隔 

第一次写的代码,空间复杂度很高,可读性差,但是运行结果没问题。

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值排序,还要先判断大小写,讲小写字符放到前面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值