347. Top K Frequent Elements

Given a non-empty array of integers, return the k most frequent elements.

Example 1:

Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]

Example 2:

Input: nums = [1], k = 1
Output: [1]

Note:

  • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        /** count each key frequency */
        for(int i = 0; i < nums.length ; i++){
            map.put(nums[i], map.getOrDefault(nums[i]) + 1);
        }

        /** sort the list */
        List<Map.Entry<Integer, Integer>> list = new LinkedList<>(map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>(){

            /** Sort values in descending order */
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });

        /** find k most frequent element */
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i< k; i++)
            res.add((Integer) list.get(i).getKey());
        return res;
    }
}

想法一样,无奈不知道如何讲map按value排序

class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {

        List<Integer>[] bucket = new List[nums.length + 1];
        Map<Integer, Integer> frequencyMap = new HashMap<Integer, Integer>();

        for (int n : nums) {
            frequencyMap.put(n, frequencyMap.getOrDefault(n, 0) + 1);
        }

        for (int key : frequencyMap.keySet()) {
            int frequency = frequencyMap.get(key);
            if (bucket[frequency] == null) {
                bucket[frequency] = new ArrayList<>();
            }
            bucket[frequency].add(key);
        }

        List<Integer> res = new ArrayList<>();

        for (int pos = bucket.length - 1; pos >= 0 && res.size() < k; pos--) {
            if (bucket[pos] != null) {
                res.addAll(bucket[pos]);
            }
        }
        return res;
    }
}

另一种方法是通过桶排序实现

把frequency对应的key存到对应数组位置

然后从后到前把key加入到res中

总结:we know we want the top k frequent elements, this means if we have numbers 1,2,3,4 whose freq are  5,6,7,8, if we want k = 2, we return 4 and 3. 

So we first use a hashmap to store elements and their freq,

then we set a bucket whose length is the number of array length + 1, why ? Because we know there are at most array length's numbers , so we can use this bucket to store their frequency

After that, we can iterate from arraylength to 1, in it have top k frequency elements.

Since there's only one and must have one correct answer, we can directly add all bucket's elements to the result.

class Solution {
    class Element{
        int val;
        int frequency;
        public Element(int val, int frequency){
            this.val = val;
            this.frequency = frequency;
        }
    }
    public int[] topKFrequent(int[] nums, int k) {
        int[] ret = new int[k];
        HashMap<Integer, Integer> map = new HashMap<>();//key is value , value is frequency
        for(int i = 0; i < nums.length; i++){
            map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        }
        PriorityQueue<Element> maxHeap = new PriorityQueue<>(nums.length, (x, y) -> Integer.compare(y.frequency, x.frequency));
        
        for(Integer key : map.keySet()){
           maxHeap.offer(new Element(key, map.get(key)));
        }
        int i = 0;
        while(i < k){
            ret[i] = maxHeap.poll().val;
            i++;
        }
        return ret;
    }
}

 

用size为k的maxheap实现

posted @ 2019-11-09 09:41  Schwifty  阅读(144)  评论(0编辑  收藏  举报