692 Top K Frequent Words

692 Top K Frequent Words

https://www.youtube.com/watch?v=0MTNMM7KSRM

compareTo(String anotherString)
Compares two strings lexicographically.

//Map.Entry<String, Integer>> 
//getValue()
// Map.Entry<String, Integer> entry : map.entrySet())
// getKey())




// Input: ["i", "love", "leetcode", "i", "love", "coding"], k = 2
// Output: ["i", "love"]


// max heap, with comparator , no alphatic order 
class Solution {
    public List<String> topKFrequent(String[] words, int k){
      HashMap<String, Integer> map = new HashMap<>();
      for(String word : words){
        if(!map.containsKey(word)){
          map.put(word, 1);
        }else{
          int count = map.get(word);
          map.put(word, count + 1);
        }
      }
      
      PriorityQueue<Map.Entry<String, Integer>> maxHeap = new PriorityQueue<>(k, new Comparator<Map.Entry<String, Integer>>(){
        @Override
        public int compare(Map.Entry<String, Integer> e1, Map.Entry<String, Integer> e2){
          if(e1.getValue() > e2.getValue()){
            return -1;
          }else if (e1.getValue() < e2.getValue()){
            return 1;
          }else{
            return 0;
          }
        }
      });
        
        
      for(Map.Entry<String, Integer> entry : map.entrySet()){
        maxHeap.offer(entry);
      }
      
      List<String> result = new ArrayList<>();
      for(int i = 0; i < k; i++){
        result.add(maxHeap.poll().getKey());
      }
        
      return result;
    }
}










// time : nlogk, n is the number of the words in total. There are k elements in the pq. So it takes logk every time we poll() one element out and 
Offer one in, and worst case is we do this n times, so n * log k           
// min heap and use comparTo 

// Line 13: error: illegal start of type
//  Collections.reverse
class Solution {
    public List<String> topKFrequent(String[] words, int k){
      HashMap<String, Integer> map = new HashMap<>();
      for(String word : words){
        if(!map.containsKey(word)){
          map.put(word, 1);
        }else{
          int count = map.get(word);
          map.put(word, count + 1);
        }
      }
      PriorityQueue<>() minHeap = new PriorityQueue<>(words.length, new Comparator<Map.Entry<String, Integer>>(){
        @Override
        public int compare(Map.Entry<String, Integer> e1, Map<Entry<String, Integer> e2){
          return e1.getValue().compareTo(e2.getValue());
        }
      });
      
      for(Map.Entry<String, Integer> entry : map.entrySet()){
        if(minHeap.size() < k){
          minHeap.offer(entry);
        }
        if(minHeap.peek().getValue() < entry.getValue()){
          minHeap.poll();
          minHeap.offer(entry);
        }
      }
      
      List<String> result = new ArrayList<>();
      while(!minHeap.isEmpty()){
        result.add(minHeap.poll().getKey());
      }
      
      return Collections.reverse(result); /// does it work?
    }
}
// hashamap to store the key: word, value: the freq 
// min heap of size k, 
// if we see a word with freq bigger than the minheap peek freq
// poll min heap, and push the new word in 

Class FreqKWords{
  public List<String> topKFreq(List<String> words, int k){
    List<String> res = new ArrayList<>();
    HashMap<String, Integer> map = new HashMap<>();
    for(String word : words){
      if(!map.containsKey(word)){
        map.put(word, 1);
      }else{
        int freq = map.get(word);
        map.put(word, freq + 1);
      }
    }
    
    // uses pq to reorder it 
    //push the first k into the minheap
    // PriorityQueue<Map.Entry<String, Integer>> maxHeap
    PriorityQueue<Map.Entry<String, Integer>> maxHeap = new PriorityQueue<>(k, new Comparator<Map.Entry<String, Integer>(){
      @Override
      public int compare(Map.Entry<String, Integer> e1, Map.Entry<String, Integer> e2){
        if(e1.getValue() < e2.getValue()){
          return -1;
        }else if(e2.getValue() > e2.getValue()){
          return 1;
        }else{
          return 0;
        }
      }
    });
    
    
    
    for(Map.Entry<String, Integer> entry: map.entrySet()){
      if(minHeap.size() < k){
        minHeap.offer(entry);
      }
      
      if(minHeap.peek().getValue < entry.getValue()){
        minHeap.poll();
        minHeap.offer(entry);
      }
    }
    
    while(!minHeap.isEmpty()){
      res.add(minHeap.poll().getKey());
    }
    return res;
  }
}

     

 这个写的少, pq 里存的 是 map.entry<string, integer>

 PriorityQueue<Map.Entry<String, Integer>> maxHeap = new PriorityQueue<>(k, new Comparator<Map.Entry<String, Integer>(){
      @Override
      public int compare(Map.Entry<String, Integer> e1, Map.Entry<String, Integer> e2){
        if(e1.getValue() < e2.getValue()){
          return -1;
        }else if(e2.getValue() > e2.getValue()){
          return 1;
        }else{
          return 0;
        }
      }
    });



自己 这些 comparator overide 要专门写, 然后 

 

 

 

maxheap(a,b). a < b, return 1

 

 

minheap(a, b) a < b,  return -1

 

 

map.entryset() 

 

map.getEntry()

 

 

 

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.

 

The idea is to keep a count of each word in a HashMap and then insert in a Priority Queue.
While inserting in pq, if the count of two words is same then insert based on string compare of the keys.

class Solution {
    public List<String> topKFrequent(String[] words, int k) {
        
        List<String> result = new LinkedList<>();
        Map<String, Integer> map = new HashMap<>();
        for(int i=0; i<words.length; i++)
        {
            if(map.containsKey(words[i]))
                map.put(words[i], map.get(words[i])+1);
            else
                map.put(words[i], 1);
        }
        
        PriorityQueue<Map.Entry<String, Integer>> pq = new PriorityQueue<>(
                 (a,b) -> a.getValue()==b.getValue() ? b.getKey().compareTo(a.getKey()) : a.getValue()-b.getValue()
        );
        
        for(Map.Entry<String, Integer> entry: map.entrySet())
        {
            pq.offer(entry);
            if(pq.size()>k)
                pq.poll();
        }

        while(!pq.isEmpty())
            result.add(0, pq.poll().getKey());
        
        return result;
    }
}

 

posted on 2018-08-10 14:34  猪猪&#128055;  阅读(169)  评论(0)    收藏  举报

导航