返回轨道
算法 · 2026-05-14 · 22 阅读

P156 前 K 个高频数字

算法 22 阅读

信号摘要

难度:Medium · 时长:15:53 · leetcode 347 · lintcode 1281

P156 前 K 个高频数字

未对外公开播放权限
点击查看说明

描述

这个题目说的是,给你一个不为空的整数数组,你要返回前 K 个出现频率最高的数字。假设给你的 K 总是有效的,也就是数组中一定包含至少 K 个不同的数字。

比如说,给你的数组是:

1, 2, 1, 2, 1, 4

给你的 K 是 2:

K = 2

在这个数组中,数字 1 出现了 3 次,数字 2 出现 2 次,数字 4 只出现 1 次。

因此,出现频率最高的两个数字是:

[1, 2]

注意,返回结果中,数字的顺序不重要,也就是说这里返回 [2, 1] 也是对的。

代码

public class AlgoCasts {

  // Time: O(n*log(k)), Space: O(n)
  public List<Integer> topKFrequentMinHeap(int[] nums, int k) {
    Map<Integer, Integer> freqMap = new HashMap<>();
    for (int num: nums) {
      int freq = freqMap.getOrDefault(num, 0);
      freqMap.put(num, freq + 1);
    }

    Queue<Map.Entry<Integer, Integer>> pq =
      new PriorityQueue<>((a, b) -> a.getValue() - b.getValue());
    for (Map.Entry<Integer, Integer> e: freqMap.entrySet()) {
      pq.add(e);
      if (pq.size() > k) pq.poll();
    }

    List<Integer> result = new ArrayList<>();
    for (Map.Entry<Integer, Integer> e: pq) result.add(e.getKey());
    return result;
  }

  private int partition(List<Map.Entry<Integer, Integer>> entries, int low, int high) {
    int pivot = entries.get(low).getValue();
    int i = low, j = high;
    while (i < j) {
      while (i < j && entries.get(j).getValue() < pivot) --j;
      if (i < j) Collections.swap(entries, i, j);
      while (i < j && entries.get(i).getValue() >= pivot) ++i;
      if (i < j) Collections.swap(entries, i, j);
    }
    return i;
  }

  // Time(avg): O(n), Time(worst): O(n^2), Space: O(n)
  public List<Integer> topKFrequentQuickSelect(int[] nums, int k) {
    Map<Integer, Integer> freqMap = new HashMap<>();
    for (int num: nums) {
      int freq = freqMap.getOrDefault(num, 0);
      freqMap.put(num, freq + 1);
    }

    List<Map.Entry<Integer, Integer>> entries = new ArrayList<>(freqMap.entrySet());
    int low = 0, high = entries.size() - 1;
    while (low <= high) {
      int p = partition(entries, low, high);
      if (p == k-1) break;
      else if (p > k-1) high = p - 1;
      else low = p + 1;
    }

    List<Integer> result = new ArrayList<>();
    for (int i = 0; i < k; ++i)
      result.add(entries.get(i).getKey());
    return result;
  }

  // Time: O(n), Space: O(n)
  public List<Integer> topKFrequentBucketSort(int[] nums, int k) {
    Map<Integer, Integer> freqMap = new HashMap<>();
    for (int num: nums) {
      int freq = freqMap.getOrDefault(num, 0);
      freqMap.put(num, freq + 1);
    }

    List<List<Integer>> buckets = new ArrayList<>(nums.length + 1);
    for (int i = 0; i <= nums.length; ++i) buckets.add(new ArrayList<>());
    for (Map.Entry<Integer, Integer> e: freqMap.entrySet())
      buckets.get(e.getValue()).add(e.getKey());

    List<Integer> result = new ArrayList<>();
    for (int i = buckets.size()-1; i >= 0 && k > 0; --i) {
      List<Integer> bucket = buckets.get(i);
      for (int j = 0; j < bucket.size() && k > 0; ++j) {
        result.add(bucket.get(j));
        --k;
      }
    }
    return result;
  }

}

📡 通讯频道