难度中等411
给定一个字符串 s
,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。
返回 已排序的字符串 。如果有多个答案,返回其中任何一个。
示例 1:
输入: s = "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。 因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
示例 2:
输入: s = "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。 注意"cacaca"是不正确的,因为相同的字母必须放在一起。
示例 3:
输入: s = "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。 注意'A'和'a'被认为是两种不同的字符。
提示:
1 <= s.length <= 5 * 105
s
由大小写英文字母和数字组成
我的题解:
func frequencySort(s string) string {
mp := make(map[rune]int)
max := 0
var str []rune
for _, v := range s{
mp[v]++
}
for _, v := range mp{
if v > max{
max = v
}
}
for ; max > 0; max--{
for i, v := range mp{
if v == max{
count := max
for ; count > 0; count--{
str = append(str, i)
}
}
}
}
return string(str)
}
官方题解:
方法一:按照出现频率排序
题目要求将给定的字符串按照字符出现的频率降序排序,因此需要首先遍历字符串,统计每个字符出现的频率,然后每次得到频率最高的字符,生成排序后的字符串。
可以使用哈希表记录每个字符出现的频率,将字符去重后存入列表,再将列表中的字符按照频率降序排序。
生成排序后的字符串时,遍历列表中的每个字符,则遍历顺序为字符按照频率递减的顺序。对于每个字符,将该字符按照出现频率拼接到排序后的字符串。例如,遍历到字符 c,该字符在字符串中出现了freq 次,则将 freq 个字符 c 拼接到排序后的字符串。
也可以使用优先队列或大根堆存储字符,读者可以自行尝试。
func frequencySort(s string) string {
cnt := map[byte]int{}//存放S中的元素(去重)并标记出现的次数,无序
for i := range s {
cnt[s[i]]++
}
type pair struct {//元素及出现次数的对数组
ch byte
cnt int
}
pairs := make([]pair, 0, len(cnt))//有序
for k, v := range cnt {
pairs = append(pairs, pair{k, v})
}
sort.Slice(pairs, func(i, j int) bool { return pairs[i].cnt > pairs[j].cnt })//顺序排列
ans := make([]byte, 0, len(s))//存放元素
for _, p := range pairs {
ans = append(ans, bytes.Repeat([]byte{p.ch}, p.cnt)...)
}
return string(ans)
}
方法二:桶排序
由于每个字符在字符串中出现的频率存在上限,因此可以使用桶排序的思想,根据出现次数生成排序后的字符串。具体做法如下:
遍历字符串,统计每个字符出现的频率,同时记录最高频率 maxFreq;
创建桶,存储从 1 到maxFreq 的每个出现频率的字符;
按照出现频率从大到小的顺序遍历桶,对于每个出现频率,获得对应的字符,然后将每个字符按照出现频率拼接到排序后的字符串。
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
func frequencySort(s string) string {
cnt := map[byte]int{}
maxFreq := 0
for i := range s {
cnt[s[i]]++
maxFreq = max(maxFreq, cnt[s[i]])
}
buckets := make([][]byte, maxFreq+1)
for ch, c := range cnt {
buckets[c] = append(buckets[c], ch)
}
ans := make([]byte, 0, len(s))
for i := maxFreq; i > 0; i-- {
for _, ch := range buckets[i] {
ans = append(ans, bytes.Repeat([]byte{ch}, i)...)
}
}
return string(ans)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}