Monday, January 21, 2019

692. Top K Frequent Words, 347. Top K Frequent Elements

692Top K Frequent Words
Given a non-empty list of words, return the k most frequent elements.
Your answer should be sorted by frequency from highest to lowest. If two words have the same frequency, then the word with the lower alphabetical order comes first.
Example 1:
Input: ["i", "love", "leetcode", "i", "love", "coding"], k = 2
Output: ["i", "love"]
Explanation: "i" and "love" are the two most frequent words.
    Note that "i" comes before "love" due to a lower alphabetical order.
Example 2:
Input: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
Output: ["the", "is", "sunny", "day"]
Explanation: "the", "is", "sunny" and "day" are the four most frequent words,
    with the number of occurrence being 4, 3, 2 and 1 respectively.
Note:
  1. You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  2. Input words contain only lowercase letters.
Follow up:
  1. Try to solve it in O(n log k) time and O(n) extra space.
---------------------------------
用PriorityQueue 来保证前k个元素,map里存所有的元素和数量
class Solution {
    class Pair{
        public String word;
        public int count;
        public Pair(String word, int count) {
            this.word = word;
            this.count = count;
        }
    }
    
    public List<String> topKFrequent(String[] words, int k) {
        Map<String, Integer> map = getMap(words);
        
        PriorityQueue<Pair> que = new PriorityQueue<>(k, (a, b) -> {
            if (a.count == b.count) {
                return b.word.compareTo(a.word);
            }
            
            return a.count - b.count;
        });
        
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            que.add(new Pair(entry.getKey(), entry.getValue()));
            if (que.size() > k) que.poll();
        }
        
        List<String> rt = new ArrayList<>();
        
        while (!que.isEmpty()) {
            rt.add(0, que.poll().word);
        }
        
        return rt;
    }
    
    private Map<String, Integer> getMap(String[] words) {
        Map<String, Integer> map = new HashMap<>();
        
        for (String word : words) {
            map.put(word, map.getOrDefault(word, 0) + 1);
        }
        
        return map;
    }
}

347Top 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.
----------------------
Solution #1
HashMap + PriorityQueue
O(n lg k)
class Solution {
    
    public List<Integer> topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int n : nums) {
            map.put(n, map.getOrDefault(n, 0) + 1);
        }
        
        PriorityQueue<Map.Entry<Integer, Integer>> que = new PriorityQueue<>((a, b) -> a.getValue() - b.getValue());
        
        for (Map.Entry<Integer, Integer> e : map.entrySet()) {
            que.add(e);
            if (que.size() > k) que.poll(); 
        }
        
        List<Integer> rt = new ArrayList<>();
        while (!que.isEmpty()) {
            rt.add(que.poll().getKey());
        }
        
        return rt;
    }
}

Solution #2, bucket sort
class Solution {
    
    public List topKFrequent(int[] nums, int k) {
        Map map = new HashMap<>();
        for (int n : nums) {
            map.put(n, map.getOrDefault(n, 0) + 1);
        }
        
        // freq -> ids    
        List[] buckets = new List[nums.length + 1];
        for (Map.Entry e : map.entrySet()) {
            int frq = e.getValue();
            if (buckets[frq] == null) {
                buckets[frq] = new ArrayList<>();
            }
            
            buckets[frq].add(e.getKey());
        }
        
        List rt = new ArrayList<>();
        for (int i = buckets.length - 1; i >= 0 && rt.size() < k; i--) {
            if (buckets[i] == null) continue;
            rt.addAll(buckets[i]);
        }
        
        return rt;
    }
}

No comments:

Post a Comment