topK问题---使用优先级队列解决

1.使用场景

Top K是很常见的一种问题,是指在N个数的无序序列中找出最大的K个数,而其中的N往往都是海量数据,对于这种问题,

  1. 最容易想到的办法当然就是先对其进行排序,然后直接取出最大的K的元素就行了,但是这种方法时间效率低而且空间开销大,排序是对所有数都要进行排序,而实际上,这类问题只关心最大的K个数,并不关心序列是否有序,因此,排序实际上是浪费了的很多资源都是没必要的
  2. 堆排序是通过维护大顶堆或者小顶堆来实现
    堆排序法来解决N个数中的TopK的思路是:先随机取出N个数中的K个数,将这N个数构造为小顶堆,那么堆顶的数肯定就是这K个数中最小的数了,然后再将剩下的N-K个数与堆顶进行比较,最后还在堆中的K个数就是TopK

2.最小的K个数

1.描述

给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。
要求:空间复杂度 O(n) ,时间复杂度 O(nlogk)

示例1
输入:
[4,5,1,6,2,7,3,8],4
返回值:
[1,2,3,4]
说明:返回最小的4个数即可,返回[1,3,2,4]也可以

2.解题思路

使用大根堆来维护k个最小元素,首先加入k个元素到优先级队列中,遍历加入后面的元素,需要做判断,如果当前元素比对顶元素还小,那么就将对顶元素抛出,加入当前的元素下沉到合适位置,直到最后一个元素判断完成,堆中的k个元素就是最小的k个元素

3.详细代码

    public ArrayList<Integer> GetLeastNumbers_Solution (int[] input, int k) {
        // write code here
        // 使用大根堆,最后在堆里的元素就是最小k个数
        ArrayList<Integer> res = new ArrayList<>();
        if (k == 0 || input.length == 0) {
            return res;
        }
        PriorityQueue<Integer> q = new PriorityQueue<>((o1,o2)->o2.compareTo(o1));
        for (int i = 0; i < k; i++) {
            q.offer(input[i]);
        }
        // 先将k个元素放入优先级队列
        for (int i = k; i < input.length; i++) {
            if (input[i] < q.peek()) {
                q.poll();
                q.offer(input[i]);
            }
        }
        // 遍历判断后面的元素
        for (int i = 0; i < k; i++) {
            res.add(q.poll());
        }
        return res;
    }

3.寻找第K大

1.描述

有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。
给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。
要求:时间复杂度 O(nlogn)O(nlogn),空间复杂度 O(1)O(1)

示例1
输入:
[1,3,5,2,2],5,3
返回值:
2

2.解题思路

使用小根堆,先加入k个元素到优先级队列中,然后将剩余元素依次加入到优先级队列中,需要判断如果当前元素比堆顶元素大,就将堆顶元素抛出,然后将当前元素加入堆中,遍历完整个数组之后,堆顶元素就是第K大的数

3.详细代码

    public int findKth (int[] a, int n, int K) {
        // write code here
        PriorityQueue<Integer> q = new PriorityQueue<>((o1, o2)->o1.compareTo(o2));
        if (K == 0 || n == 0) {
            return 0;
        }
        for (int i = 0; i < K; i++) {
            q.offer(a[i]);
        }
        for (int i = K; i < n; i++) {
            if (a[i] > q.peek()) {
                q.poll();
                q.offer(a[i]);
            }
        }
        return q.peek();
    }

你可能感兴趣的:(Java语法,牛客101,python,算法,数据结构)