• 给定一个字符串,根据字符出现频率排序--Java实现


    题目描述:

    给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

    示例 1:

    输入:
    "tree"
    输出:
    "eert"
    解释:
    'e'出现两次,'r'和't'都只出现一次。
    因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。

    示例 2:

    输入:
    "cccaaa"
    输出:
    "cccaaa"
    解释:
    'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
    注意"cacaca"是不正确的,因为相同的字母必须放在一起。

    示例 3:

    输入:
    "Aabb"
    输出:
    "bbAa"
    解释:
    此外,"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));
        }
    }
    
    
  • 相关阅读:
    supervisord + docker run = web页面管理运行的docker
    docker之Dockerfile实践用dockerfile构建nginx环境
    Dockerfile文件详解
    【docker】CMD ENTRYPOINT 区别 终极解读!
    golang html/template
    网络连接带宽的理论最大值
    Queue length 和 Queue depth 的区别
    .tar.gz 文件和 .tar.xz 文件的区别
    如何同时在Isilon的所有网卡上抓取网络包?
    Reimage Isilon cluster,结果忘记了修改管理口的netmask,怎么办?
  • 原文地址:https://www.cnblogs.com/cdlyy/p/12066766.html
Copyright © 2020-2023  润新知