1
1
package com .fishercoder .solutions ;
2
2
3
- import java .util .ArrayList ;
4
- import java .util .HashMap ;
5
- import java .util .List ;
6
- import java .util .Map ;
3
+ import java .util .*;
7
4
import java .util .Map .Entry ;
8
- import java .util .PriorityQueue ;
9
- import java .util .Queue ;
10
- import java .util .TreeMap ;
11
5
12
6
public class _347 {
13
7
14
8
public static class Solution1 {
15
9
/**
16
- * Use buckets to hold numbers of the same frequency
17
- * It's averaged at 30 ms on Leetcode.
10
+ * Bucket sort:
11
+ * Use buckets to hold numbers of the same frequency, some buckets might be empty while the rest might have more than one element.
12
+ * This editorial explains it well enough: https://leetcode.com/problems/top-k-frequent-elements/editorial/ starting from 08'55".
13
+ * <p>
14
+ * This is the most optimal solution.
15
+ * Time: O(n)
16
+ * Space: O(n)
18
17
*/
19
18
public int [] topKFrequent (int [] nums , int k ) {
20
19
Map <Integer , Integer > map = new HashMap ();
21
- for (int i : nums ) {
22
- map .put (i , map .getOrDefault (i , 0 ) + 1 );
20
+ for (int num : nums ) {
21
+ map .put (num , map .getOrDefault (num , 0 ) + 1 );
23
22
}
24
-
25
- ArrayList [] bucket = new ArrayList [nums .length + 1 ];
26
- for (Entry <Integer , Integer > e : map .entrySet ()) {
27
- int frequency = e .getValue ();
28
- if (bucket [frequency ] == null ) {
29
- bucket [frequency ] = new ArrayList <Integer >();
23
+ //use nums.length + 1, so that we can directly use the frequency as the index for this array
24
+ //how this buckets look like is: buckets[1] holds numbers that have frequency one, buckets[2] holds numbers that have frequency two, etc.
25
+ //so, the numbers that have the highest frequencies are on the right-most side.
26
+ List [] bucket = new ArrayList [nums .length + 1 ];
27
+ for (Entry <Integer , Integer > entry : map .entrySet ()) {
28
+ int freq = entry .getValue ();
29
+ if (bucket [freq ] == null ) {
30
+ bucket [freq ] = new ArrayList <Integer >();
30
31
}
31
- bucket [frequency ].add (e .getKey ());
32
+ bucket [freq ].add (entry .getKey ());
32
33
}
33
- List < Integer > result = new ArrayList <>() ;
34
- for (int i = bucket .length - 1 ; i >= 0 && result . size () < k ; i --) {
34
+ int [] result = new int [ k ] ;
35
+ for (int i = bucket .length - 1 , l = 0 ; i >= 0 && l < k ; i --) {
35
36
if (bucket [i ] != null ) {
36
37
for (int j = 0 ; j < bucket [i ].size (); j ++) {
37
- result . add (( int ) bucket [i ].get (j ) );
38
+ result [ l ++] = ( int ) bucket [i ].get (j );
38
39
}
39
40
}
40
41
}
41
- int [] arr = new int [result .size ()];
42
- for (int i = 0 ; i < arr .length ; i ++) {
43
- arr [i ] = result .get (i );
44
- }
45
- return arr ;
42
+ return result ;
46
43
}
47
44
}
48
45
49
46
public static class Solution2 {
50
47
/**
51
- * Use hashtable and heap, it's averaged at 100 ms on Leetocde.
48
+ * Use hashtable and heap.
49
+ * Time: O(nlogn)
50
+ * Space: O(n)
52
51
*/
53
52
public int [] topKFrequent (int [] nums , int k ) {
54
53
// construct the frequency map first, and then iterate through the map
@@ -58,7 +57,7 @@ public int[] topKFrequent(int[] nums, int k) {
58
57
map .put (num , map .getOrDefault (num , 0 ) + 1 );
59
58
}
60
59
61
- // build heap, this is O(logn )
60
+ // build heap, this is O(nlogn )
62
61
Queue <Entry <Integer , Integer >> heap = new PriorityQueue <>((o1 , o2 ) -> o2 .getValue () - o1 .getValue ());
63
62
for (Entry <Integer , Integer > entry : map .entrySet ()) {
64
63
heap .offer (entry );
@@ -75,34 +74,4 @@ public int[] topKFrequent(int[] nums, int k) {
75
74
return arr ;
76
75
}
77
76
}
78
-
79
- public static class Solution3 {
80
- /**
81
- * Use hashtable and heap, it's averaged at 10 ms on Leetocde.
82
- */
83
- public int [] topKFrequent (int [] nums , int k ) {
84
- Map <Integer , Integer > map = new HashMap <>();
85
- for (int i : nums ) {
86
- map .put (i , map .getOrDefault (i , 0 ) + 1 );
87
- }
88
- TreeMap <Integer , List <Integer >> treeMap = new TreeMap <>((a , b ) -> b - a );
89
- for (int key : map .keySet ()) {
90
- List <Integer > list = treeMap .getOrDefault (map .get (key ), new ArrayList <>());
91
- list .add (key );
92
- treeMap .put (map .get (key ), list );
93
- }
94
- List <Integer > list = new ArrayList <>();
95
- while (!treeMap .isEmpty ()) {
96
- list .addAll (treeMap .pollFirstEntry ().getValue ());
97
- if (list .size () == k ) {
98
- break ;
99
- }
100
- }
101
- int [] ans = new int [list .size ()];
102
- for (int i = 0 ; i < list .size (); i ++) {
103
- ans [i ] = list .get (i );
104
- }
105
- return ans ;
106
- }
107
- }
108
77
}
0 commit comments