开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情
LeetCode451:根据字符出现频率排序
给定一个字符串 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'被认为是两种不同的字符。
提示:
s由大小写英文字母和数字组成
思路分析
题目要求按字符出现的频率降序排,可以想到使用大根堆来实现降序,而统计每个字符频率使用哈希表,在堆中存放数据应包含字符以及该字符出现的次数,所以新增加一个数据类。
1.使用哈希表:key为当前字符,value为该字符出现次数。遍历整个字符串,将每个字符出现次数存入哈希表中;
2.创建一个数据类Data,包含一个char类型的字符和int类型的次数;
3.新建优先队列,即大根堆; [注]:优先队列默认以小根堆方式,此次需要修改为大根堆;
4.遍历哈希表,存入大根堆中;
5.新建StringBuilder,将大根堆中数据依次出堆,即可得到最终结果。
算法代码
//创建一个数据类Data,包含一个char类型的字符和int类型的次数
public class Data {
public char c;
public int count;
public Data(char c, int count) {
this.c = c;
this.count = count;
}
public char getC() {
return this.c;
}
public int getCount() {
return this.count;
}
}
public String frequencySort(String s) {
Map < Character, Integer > map = new HashMap < > ();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
PriorityQueue < Data > heap = new PriorityQueue < Data > (new Comparator < Data > () {
public int compare(Data d1, Data d2) {
return d2.getCount() - d1.getCount(); //大根堆
}
});
for (Map.Entry < Character, Integer > entry: map.entrySet()) {
heap.offer(new Data(entry.getKey(), entry.getValue()));
}
StringBuilder sb = new StringBuilder();
while (!heap.isEmpty()) {
Data data = (Data) heap.poll();
for (int i = 0; i < data.getCount(); i++) {
sb.append(data.getC());
}
}
return sb.toString();
}
结果详情
算法复杂度
- 空间复杂度:
- 时间复杂度:
在掘金(JUEJIN)一起进步,一起成长!