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

For example,
Given [1,1,1,2,2,3] and k = 2, return [1,2].

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.

O(n log k) solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
if (nums == null || k <= 0) return null;
HashMap<Integer, Integer> counts = new HashMap<>();
for (int num : nums) {
counts.put(num, counts.getOrDefault(num, 0) + 1);
}

PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>((a, b) -> a.getValue() - b.getValue());
for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
pq.offer(entry);
if (pq.size() > k) {
pq.poll();
}
}

List<Integer> res = new LinkedList<>();
while (pq.size() != 0) {
res.add(0, pq.poll().getKey());
}
return res;
}
}

O(n) bucket sort solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
if (nums == null || k <= 0) return null;
HashMap<Integer, Integer> counts = new HashMap<>();
for (int num : nums) {
counts.put(num, counts.getOrDefault(num, 0) + 1);
}

List<Integer>[] buckets = new List[nums.length + 1];
for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
int index = entry.getValue();
if (buckets[index] == null) {
buckets[index] = new LinkedList<>();
}
buckets[entry.getValue()].add(entry.getKey());
}

List<Integer> res = new LinkedList<>();
for (int i = buckets.length - 1; i >= 0 && res.size() < k; i--) {
if (buckets[i] != null) {
res.addAll(buckets[i]);
}
}
return res;
}
}