题目描述:
给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
示例 1:
输入:
"tree"
"tree"
输出:
"eert"
"eert"
解释:
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
示例 2:
输入:
"cccaaa"
"cccaaa"
输出:
"cccaaa"
"cccaaa"
解释:
'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。
'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。
示例 3:
输入:
"Aabb"
"Aabb"
输出:
"bbAa"
"bbAa"
解释:
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A'和'a'被认为是两种不同的字符。
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A'和'a'被认为是两种不同的字符。
解题思路:
用一个map来存每个字符出现的次数(键为字符,值为出现的次数),再将map中的entry按值来从大到小排序,然后再连接起来(根据map的值对应的key进行拼接)。
Map没有按值排序的方法,java有Comparator比较器接口,但要求的参数是list,我们可以通过Arraylist构造函数把map.entrySet()转化为list,就可以用比较器了。
Comparator比较器接口:
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);我们可以建立一个“比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。
Collections.sort(list,
new
PriceComparator())
参数一:需要排序的list
参数二:比较器,实现Comparator接口的类,返回一个
int
型的值,就相当于一个标志,告诉sort方法按什么顺序来对list进行排序。
Comparator是个接口,可重写compare()及equals()这两个方法,用于比较功能;如果是
null
的话,就是使用元素的默认顺序,如a,b,c,d,e,f,g,就是a,b,c,d,e,f,g这样,当然数字也是这样的。
compare(a,b)方法:根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
equals(obj)方法:仅当指定的对象也是一个 Comparator,并且强行实施与此 Comparator 相同的排序时才返回
true
。
代码实现:
import java.util.*; public class FrequencySort { public static String frequencySort(String s) { if (s.length() < 3){ return s; } // 查找表(将数据存到一个表里,然后查找)map查找比list更优(更适合查找) Map<Character, Integer> counter = new HashMap<>(); for (int i = 0; i < s.length(); i++) { counter.put(s.charAt(i), counter.getOrDefault(s.charAt(i), 0) + 1); } //通过Arraylist构造函数把map.entrySet()转化为list(map没有按值排序的方法,我们要把map转化为list) List<Map.Entry<Character, Integer>> list = new ArrayList<>(counter.entrySet()); //用Comparator比较器进行排序 Collections.sort(list, new Comparator<Map.Entry<Character, Integer>>() { @Override public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) { //从大到小逆序排序 return o1.getValue() > o2.getValue() ? -1 : 1; } }); StringBuilder res = new StringBuilder(); //遍历排好序的列表,得到排好序的集合,然后按值遍历,将键key放到res中,输出字符串) for (Map.Entry<Character, Integer> entry : list) { //对每一个值进行遍历,例如a出现三次,遍历3次,将a加入res,e出现2词,遍历2次,将e加入res...... for (int i = 0; i < entry.getValue(); i++) { res.append(entry.getKey()); } } return res.toString(); } public static void main(String[] args){ String str = "traaaee"; System.out.print(frequencySort(str)); } }