image.png

解题思路

堆排序

image.png

  1. public List<Integer> topKFrequent(int[] nums, int k) {
  2. // 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
  3. HashMap<Integer,Integer> map = new HashMap();
  4. for(int num : nums){
  5. if (map.containsKey(num)) {
  6. map.put(num, map.get(num) + 1);
  7. } else {
  8. map.put(num, 1);
  9. }
  10. }
  11. // 遍历map,用最小堆保存频率最大的k个元素
  12. PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
  13. @Override
  14. public int compare(Integer a, Integer b) {
  15. return map.get(a) - map.get(b);
  16. }
  17. });
  18. for (Integer key : map.keySet()) {
  19. if (pq.size() < k) {
  20. pq.add(key);
  21. } else if (map.get(key) > map.get(pq.peek())) {
  22. pq.remove();
  23. pq.add(key);
  24. }
  25. }
  26. // 取出最小堆中的元素
  27. List<Integer> res = new ArrayList<>();
  28. while (!pq.isEmpty()) {
  29. res.add(pq.remove());
  30. }
  31. return res;
  32. }

桶排序法

image.png

 public List<Integer> topKFrequent(int[] nums, int k) {
        List<Integer> res = new ArrayList();
        // 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
        HashMap<Integer,Integer> map = new HashMap();
        for(int num : nums){
            if (map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }

        //桶排序
        //将频率作为数组下标,对于出现频率不同的数字集合,存入对应的数组下标
        List<Integer>[] list = new List[nums.length+1];
        for(int key : map.keySet()){
            // 获取出现的次数作为下标
            int i = map.get(key);
            if(list[i] == null){
                list[i] = new ArrayList();
            }
            list[i].add(key);
        }

        // 倒序遍历数组获取出现顺序从大到小的排列
        for(int i = list.length - 1;i >= 0 && res.size() < k;i--){
            if(list[i] == null) continue;
            res.addAll(list[i]);
        }
        return res;
    }