Long time did not write a blog, October busy mother motherland birthday Amby (I know this is not a reason to not write a blog), in early November to really run around rations laboratory, a business trip, is busy the bruised and battered, but still do not know the back there is no concrete results. Poor two-eleven to buy things are not bought, they said, two-eleven false sales figures, in fact, I think this is the big company inside a given KPI, maybe before the two-eleven has been based on historical sales this year will sales of fixed index distribution has become a go, then everyone's ability to chop hand did not disappoint, just to fulfill the requirements, the satisfaction of all of it. I and so didodecyl it emmmm, less routine, simplify it. Digress, back to the topic now, today, before the use of Comparator interface done a few questions to share with you.
A description of the problem
Given a non-null integer array, the frequency of occurrence of which the first returns the k higher element.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2 Output: [1,2]
Note: You can always assume a given rational k, and the number of array elements is not the same 1 ≤ k ≤. Your time complexity of the algorithm must be better than O (n log n), n is the size of the array.
answer
Topic description is quite simple, the number of times each element appears just to the statistics come out, and then take the first k elements to the number of occurrences.
Method a: The Hash + using the Map value in descending order of the key
. 1 / ** 2 * + to the hash Key Map for sorting 20ms . 3 * @param the nums int array . 4 * @param first k k-th largest frequencies . 5 * @return k elements . 6 * / . 7 public List <Integer> topKFrequent ( int [ ] the nums, int K) { . 8 the Map <Integer, Integer> = the hash new new the HashMap <> (); . 9 for ( int A: the nums) { 10 hash.put (A, hash.getOrDefault (A, 0) +. 1 ) ; 11 } 12 13 List<Map.Entry<Integer, Integer>> list = new ArrayList<>(hash.entrySet()); 14 Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() { 15 public int compare(Map.Entry<Integer, Integer> o1, 16 Map.Entry<Integer, Integer> o2) { 17 return o2.getValue().compareTo(o1.getValue()); 18 } 19 }); 20 21 List<Integer> ret = new ArrayList<>(); 22 ListIterator<Map.Entry<Integer, Integer>> it = list.listIterator(); 23 while (it.hasNext() && k > 0) { 24 Map.Entry<Integer, Integer> entry = it.next(); 25 ret.add(entry.getKey()); 26 k --; 27 } 28 return ret; 29 }
Since the time complexity of sorting is O (nlgn), n is the size of the map, the condition.
Method 2: Using a small stack top storage key, sorted in ascending order according to the key value corresponding to
. 1 / ** 2 * + mapping the hash heap sort 19ms . 3 * . 4 * default in the Java heap is a small top, the stack elements are key, but is the corresponding comparison value, so it is passed to the comparator and implement Comparator . 5 * / . 6 public static List <Integer> topKFrequent2 ( int [] the nums, int K) { . 7 the Map <Integer, Integer> Map = new new the HashMap <> (); . 8 . 9 // Key: the nums elements, value: key appears the number 10 for ( int A: the nums) { . 11 map.put (A, map.getOrDefault (A, 0) +. 1 ); 12 is } 13 is 14 PriorityQueue<Integer> minHeap = new PriorityQueue<>(new Comparator<Integer>() { 15 @Override 16 public int compare(Integer a, Integer b) { 17 // 升序 18 return map.get(a) - map.get(b); 19 } 20 }); 21 22 for (int key : map.keySet()) { 23 if (minHeap.size() < k) { 24 minHeap.offer(key); 25 } else if (map.get (key)> map.get (minHeap.peek ())) { 26 minHeap.poll (); 27 minHeap.offer (key); 28 } 29 } 30 return new ArrayList <> (minHeap); 31 }
Since the construction of the stack time complexity is O (klgk), inserting a new element each time when the maintenance operation time complexity of the maximum height of the pile O (lgk), n times the maximum maintenance time complexity O (nlgk), so To meet the conditions.
Second problem description
To a non-empty list of words, before returning to k th highest number of word appears.
The answer should be returned sorted in descending frequency word appears. If the same word has a different frequency, sorted alphabetically.
Input: [ "i", "love ", "leetcode", "i", "love", "coding"], k = 2
Output: [ "i", "love "]
Analytical: "i" and "love "as two words appear most frequently, are 2 times.
Note that, "i" in alphabetical order before the "love".
Input: [ "the", "day ", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
Output: [ "the", "is", "sunny", "day"]
resolve: "the", "is" , "sunny" and "day" is four words appear most frequently,
the number of occurrences were 4, 3, 2 and 1.
answer
This question and a question on the same idea, only a statistical frequency and then ordering for strings, but also pay attention if the two strings appear the same number, then sorted according to the lexicographical string. Corresponds to the premise in the output string is output in the descending order of occurrence, the same number of occurrences of the string, the string dictionary output in ascending order. So are two different collations, when introduced into the comparator, a plurality of determination conditions.
Method One: hash + sort Map
using the stored hash TreeMap, the default key is stored in lexicographic order of
. 1 / ** 2 * Map sort of the hash + 11ms, the time complexity is O (mlgm), m represents the m types of different strings . 3 * @param S . 4 * @param K . 5 * @return . 6 * / . 7 public List <String> topKFrequent (String [] S, int K) { . 8 the hash = the Map <String, Integer> new new the TreeMap <> (); . 9 10 for (STR String: S) { . 11 hash.put (STR, hash.getOrDefault (STR, 0) +. 1 ); 12 is } 13 is 14 List<Map.Entry<String, Integer>> list = new ArrayList<>(hash.entrySet()); 15 16 Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() { 17 public int compare(Map.Entry<String, Integer> o1, 18 Map.Entry<String, Integer> o2) { 19 // list 会降序 20 return o2.getValue().compareTo(o1.getValue()); 21 } 22 }); 23 24 ListIterator<Map.Entry<String, Integer>> it = list.listIterator(); 25 List<String> ret = new ArrayList<>(); 26 while (it.hasNext() && k > 0) { 27 Map.Entry<String, Integer> entry = it.next(); 28 ret.add(entry.getKey()); 29 k --; 30 } 31 return ret; 32 }
Method two: hash + heapsort
Since the answer is in accordance with the output frequency and the output string in reverse order, the same number of output when character strings lexicographic order. Therefore, when the stack stored, sorted according to the sequence number of occurrences, the number of the same, sorted in descending lexicographic occur. Finally, the results of time and then pounded into the reverse look, we get the result of questions asked.
. 1 / ** 2 * + heap sort the hash 9 ms, the overall complexity reached O (nlgk), n is the number string, k is the size of the heap. . 3 * @param S strings . 4 * @param number K . 5 * @return strings . 6 * / . 7 public List <String> topKFrequent2 (String [] S, int {K) . 8 the Map <String, Integer> = the hash new new the HashMap < > (); . 9 10 for (STR String: S) { . 11 hash.put (STR, hash.getOrDefault (STR, 0) +. 1 ); 12 is } 13 is 14 PriorityQueue<String> h = new PriorityQueue<>(new Comparator<String>() { 15 @Override 16 public int compare(String o1, String o2) { 17 return hash.get(o1).equals(hash.get(o2)) ? 18 // 按照 次数 升序 19 // o2.compareTo(o1) : hash.get(o1).compareTo(hash.get(o2)); 20 o2.compareTo(o1) : (hash.get(o1) - hash.get(o2)); 21 } 22 }); 23 24 //The key is stored in, the rule is to be stored in ascending order of the number of key occurs, if they are the same number, in descending order according to the key dictionary 25 for (String key: hash.keySet ()) { 26 is h.offer (key) ; 27 IF (h.size ()> k) h.poll (); 28 } 29 30 // save the results, and also need to reverse it, this is achieved in descending order according to the number, the same number of words, according to the dictionary ascending order 31 is List <String> RET = new new the ArrayList <> (); 32 the while (! ret.add (h.poll ()) h.isEmpty ()); 33 is 34 is Collections.reverse (RET); 35 return RET; 36 }