本题需要统计字符个数,并按逆序排序,共有三种解法:
1.用数组存储排序,先将字符串转为字符数组,调用Arrays.sort方法对字符数组排序,将相同的字符存储在一个字符串中,将所有字符串存入list中,按照每个字符串长度由大到小进行排序,新建一个StringBuilder,将排好序的字符串依次添加到StringBuilder中,最后转成String输出。
2.HashMap存储排序,用HashMap统计字符及出现次数,存入count中,对count的value值进行排序,然后依次添加字符到StringBuilder中,最后转成String输出。
3.桶排序,用HashMap统计字符及出现次数,存入count中,遍历count得到最大的value,用ArrayList建立value个空桶,将字符放入桶中,桶的顺序是字符出现的频次,从后向前遍历每个桶中的字符,添加到StringBuilder中,最后转成String输出。
语法补充:
1.Comparator比较器复写方法
Collections.sort(list, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getId() - o2.getId(); } };
list.sort(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getId() - o2.getId(); } });
Collections.sort(list, (a, b) -> b.getId()-a.getId());
2.将map按Value大小逆序排序,需要利用map.entrySet()并存入list中[(Character1,Integer1), (Character2,Integer2)]
//首先将count放入list List<Map.Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(count.entrySet());//[(Character1,Integer1), (Character2,Integer2)] //用list对Comparator复写,实现按map的Value逆序排序 list.sort(new Comparator<Map.Entry<Character, Integer>>(){ @Override public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer>o2){ return o2.getValue()-o1.getValue(); } });
3.遍历map对象
Map<Integer, Integer> map = new HashMap<Integer, Integer>(); for (Map.Entry<Integer, Integer> entry : map.entrySet()) { System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } //遍历map中的键 for (Integer key : map.keySet()) { System.out.println("Key = " + key); } //遍历map中的值 for (Integer value : map.values()) { System.out.println("Value = " + value); }
JAVA
class Solution { public String frequencySort(String s) { if(s == null || s.isEmpty()) return s; StringBuilder res = new StringBuilder(); //将字符串转成字符数组并排序 char[] chars = s.toCharArray(); Arrays.sort(chars); //将字符相同的存入一个字符串,并将所有字符串存入list List<String> charStrings = new LinkedList<>(); StringBuilder temp = new StringBuilder(); temp.append(chars[0]); for(int i = 1; i < chars.length; i++){ if(chars[i] != chars[i-1]){ charStrings.add(temp.toString()); temp = new StringBuilder(); } temp.append(chars[i]); } charStrings.add(temp.toString()); //对list 按照字符串长度从大到小排序 Collections.sort(charStrings, (a, b) -> b.length()-a.length()); //将排序后的字符串依次存入结果 for(String str : charStrings){ res.append(str); } return res.toString(); } }
class Solution { public String frequencySort(String s) { StringBuilder res = new StringBuilder(); Map<Character, Integer> count = new HashMap<>(); for(char c: s.toCharArray()){ count.put(c, count.getOrDefault(c, 0)+1); } //首先将count放入list List<Map.Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(count.entrySet());//[(Character1,Integer1), (Character2,Integer2)] //用list对Comparator复写,实现按map的Value逆序排序 list.sort(new Comparator<Map.Entry<Character, Integer>>(){ @Override public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer>o2){ return o2.getValue()-o1.getValue(); } }); for (Map.Entry<Character, Integer> map : list){ for(int i = 0; i < map.getValue(); i++){ res.append(map.getKey()); } } return res.toString(); } }
class Solution { public String frequencySort(String s) { if(s == null || s.isEmpty()) return s; StringBuilder res = new StringBuilder(); Map<Character, Integer> count = new HashMap<>(); for(char c: s.toCharArray()){ count.put(c, count.getOrDefault(c, 0)+1); } int maxFrequency = 0; for(Map.Entry<Character, Integer> entry: count.entrySet()){ maxFrequency = Math.max(maxFrequency, entry.getValue()); } System.out.println(maxFrequency); //申请一排桶,桶的顺序代表桶内字符出现的次数 List<List<Character>> buckets = new ArrayList<>(); //bug 这里写成LinkedList会超时,因为单个字符出现次数多的时候,需要访问的桶也增多。 //ArrayList访问速度快,LinkedList增加删除速度快 //构建空桶 for(int i = 0; i <= maxFrequency; i++){ buckets.add(new LinkedList<Character>()); } //根据字符出现的次数放入对应的桶内 for(Character key: count.keySet()){ int freq = count.get(key); buckets.get(freq).add(key); //!!!桶排序最重要的一步 } for(int i =buckets.size()-1; i >= 1; i--){ for(Character c: buckets.get(i)){//一个桶内可能有多个字符 for(int j = 0; j < i; j++){ res.append(c); } } } return res.toString(); } }