Top K Frequent Elements Leetcode
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.
这道题用hashmap和priorityqueue很快就通过了。需要注意的是priorityqueue默认是最小堆,所以写comparator的时候要注意反过来写。
感觉自己最近的代码还挺优雅的,而且除了忘记了最小堆还有一个右括号一遍就过了,有进步哈哈哈。
public class Solution { public List<Integer> topKFrequent(int[] nums, int k) { List<Integer> res = new ArrayList<>(); if (nums == null || nums.length == 0) { return res; } Map<Integer, Integer> hm = new HashMap<>(); for (int i = 0; i < nums.length; i++) { hm.put(nums[i], hm.getOrDefault(nums[i], 0) + 1); } PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>(){ public int compare(Integer n1, Integer n2) { return hm.get(n2) - hm.get(n1); } }); for (Integer n : hm.keySet()) { pq.add(n); } for (int i = 0; i < k; i++) { res.add(pq.poll()); } return res; } }
不过高兴了半天发现时间复杂度是O(nlogn)着实伤心。。。还是要用bucket sort来实现比较好。学习了。
bucket sort, 桶排序就是先把数组按一定的规则排到bucket里面,此题是按照频率来排序,然后从后往前输出。
public class Solution { public List<Integer> topKFrequent(int[] nums, int k) { List<Integer> res = new ArrayList<>(); if (nums == null || nums.length == 0) { return res; } Map<Integer, Integer> hm = new HashMap<>(); for (int i = 0; i < nums.length; i++) { hm.put(nums[i], hm.getOrDefault(nums[i], 0) + 1); } List[] bucket = new List[nums.length + 1]; for (int key : hm.keySet()) { int value = hm.get(key); if (bucket[value] == null) { bucket[value] = new ArrayList<Integer>(); } bucket[value].add(key); } for (int i = bucket.length - 1, j = 0; i >=0 && res.size() < k; i--) { if (bucket[i] != null) { res.addAll(bucket[i]); } } return res.subList(0, k); } }
这个时间复杂度是O(n)了。介于最后一个桶的个数可能大于k,所以最好的是返回个数为k的sublist。