一. 题目

二. 思路

1. 堆

2. 快排

3. 桶排序

  • 哈希统计数量,然后将其放到数量-1的索引位置,最后遍历后k个数。O(n)时间复杂度。

三. 代码

1. 堆

class Solution
{
    final Map<Integer, Integer> cnt = new HashMap<>();
    final Queue<Map.Entry<Integer, Integer>> q = new PriorityQueue<>(Comparator.comparingInt(Map.Entry::getValue));

    public int[] topKFrequent(int[] nums, int k)
    {
        cnt.clear();
        q.clear();
        for (Integer v : nums)//统计次数
            cnt.put(v, cnt.getOrDefault(v, 0) + 1);

        for (Map.Entry<Integer, Integer> e : cnt.entrySet())
            if (q.size() < k) q.offer(e);
            else
            {
                Map.Entry<Integer, Integer> minv = q.peek();
                if (minv.getValue() < e.getValue())
                {
                    q.poll();
                    q.offer(e);
                }
            }
        return q.stream().mapToInt(Map.Entry::getKey).toArray();
    }
}

2. 快排

class Solution
{
    static final ThreadLocalRandom rnd = ThreadLocalRandom.current();
    final Map<Integer, Integer> cnt = new HashMap<>();
    final List<Map.Entry<Integer, Integer>> a = new ArrayList<>();

    private void quickSort(int l, int r, int k)//逆序排,这样前k大的就是数组前k个
    {
        if (l >= r) return;
        int mi = rnd.nextInt(l, r + 1);
        Map.Entry<Integer, Integer> mv = a.get(mi);
        Collections.swap(a, mi, l);//交换首和轴

        int i = l, j = r;
        while (i < j)
        {
            while (i < j && a.get(j).getValue() <= mv.getValue()) --j;
            Collections.swap(a, i, j);

            while (i < j && a.get(i).getValue() >= mv.getValue()) ++i;
            Collections.swap(a, i, j);
        }
        a.set(i, mv);

        int c = i - l + 1;
        if (c == k) return;
        if (c < k) quickSort(i + 1, r, k - c);
        else quickSort(l, i - 1, k);
    }

    public int[] topKFrequent(int[] nums, int k)
    {
        a.clear();
        cnt.clear();
        for (Integer v : nums)//统计次数
            cnt.put(v, cnt.getOrDefault(v, 0) + 1);

        a.addAll(cnt.entrySet());
        quickSort(0, a.size() - 1, k);
        return a.stream().limit(k).mapToInt(Map.Entry::getKey).toArray();
    }
}

3. 桶排序

class Solution
{
    static final ThreadLocalRandom rnd = ThreadLocalRandom.current();
    final Map<Integer, Integer> cnt = new HashMap<>();

    public int[] topKFrequent(int[] nums, int k)
    {
        cnt.clear();
        for (Integer v : nums)//统计次数
            cnt.put(v, cnt.getOrDefault(v, 0) + 1);

        List<Integer>[] a = (List<Integer>[]) new List[nums.length];
        for (Map.Entry<Integer, Integer> entry : cnt.entrySet())
        {
            int key = entry.getKey(), value = entry.getValue() - 1;
            if (a[value] == null) a[value] = new ArrayList<>();
            a[value].add(key);
        }

        List<Integer> ans = new ArrayList<>();
        for (int i = nums.length - 1; ans.size() < k; --i)
            if (a[i] != null)
                ans.addAll(a[i]);
        return ans.stream().mapToInt(Integer::intValue).toArray();
    }
}