题目

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

Example 1:

  1. Input: nums = [1,1,1,2,2,3], k = 2
  2. Output: [1,2]

Example 2:

  1. Input: nums = [1], k = 1
  2. Output: [1]

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.
  • It’s guaranteed that the answer is unique, in other words the set of the top k frequent elements is unique.
  • You can return the answer in any order.

题意

求一个数组中出现次数最多的前k个元素。要求时间复杂度小于0347. Top K Frequent Elements (M) - 图1

思路

最直接的方法是维护一个最大大小为k的小顶堆,向其中添加数组中的不重复元素,按照出现次数排序,如果添加后堆大小为k+1,则将堆顶元素去除,这样最终留下的就是k个出现次数最多的元素,复杂度为0347. Top K Frequent Elements (M) - 图2

top k类型的问题还可以用寻找第K大来解决,平均复杂度为0347. Top K Frequent Elements (M) - 图3


代码实现

Java

优先队列

  1. class Solution {
  2. public int[] topKFrequent(int[] nums, int k) {
  3. Map<Integer, Integer> record = new HashMap<>();
  4. Queue<Integer> q = new PriorityQueue<>((a, b) -> record.get(a) - record.get(b));
  5. for (int num : nums) {
  6. record.put(num, record.getOrDefault(num, 0) + 1);
  7. }
  8. for (int num : record.keySet()) {
  9. q.offer(num);
  10. if (q.size() > k) {
  11. q.poll();
  12. }
  13. }
  14. int[] res = new int[k];
  15. int i = 0;
  16. while (!q.isEmpty()) {
  17. res[i++] = q.poll();
  18. }
  19. return res;
  20. }
  21. }

快速选择

  1. class Solution {
  2. public int[] topKFrequent(int[] nums, int k) {
  3. Map<Integer, Integer> record = new HashMap<>();
  4. for (int num : nums) {
  5. record.put(num, record.getOrDefault(num, 0) + 1);
  6. }
  7. int[] arr = new int[record.size()];
  8. int i = 0;
  9. for (int num : record.keySet()) {
  10. arr[i++] = num;
  11. }
  12. int left = 0, right = arr.length - 1;
  13. int[] res = new int[k];
  14. while (left <= right) {
  15. int mid = partition(arr, left, right, record);
  16. if (k - 1 < mid) {
  17. right = mid - 1;
  18. } else if (k - 1 > mid) {
  19. left = mid + 1;
  20. } else {
  21. for (int j = 0; j < k; j++) {
  22. res[j] = arr[j];
  23. }
  24. return res;
  25. }
  26. }
  27. return res;
  28. }
  29. private int partition(int[] arr, int left, int right, Map<Integer, Integer> record) {
  30. int tmp = arr[left];
  31. while (left < right) {
  32. while (left < right && record.get(arr[right]) < record.get(tmp)) {
  33. right--;
  34. }
  35. arr[left] = arr[right];
  36. while (left < right && record.get(arr[left]) >= record.get(tmp)) {
  37. left++;
  38. }
  39. arr[right] = arr[left];
  40. }
  41. arr[left] = tmp;
  42. return left;
  43. }
  44. }