Top K问题
1、在一组非常大量的数据中找出前100大的数据
(1)每次选出101个数进行排序,最后一个数删除,多次排序(垃圾算法,时间复杂度高)
1 | package com.zhangrui.sort; |
(2)大顶堆,优先队列 PriorityQueue,建立一个大小为K的队列(可以直接使用java中的优先队列 PriorityQueue,基于 优先级堆的极大优先级队列,队列中元素默认按照自然顺序排序,数字就是默认最小的放在队列头)如果队列中有空位可以直接添加元素,如有元素个数达到K,将要添加的元素与优先队列中的队首(也就是优先队列中最小的数)进行比较,选出最小的元素放在队列头
时间复杂度为O(nlogk)
队列中方法说明:
**offer()**方法往队列添加元素如果队列已满直接返回false,队列未满则直接插入并返回true
**add()**方法是对offer()方法的简单封装.如果队列已满,抛出异常new IllegalStateException(“Queue full”);
**put()**方法往队列里插入元素,如果队列已经满,则会一直等待直到队列为空插入新元素,或者线程被中断抛出异常 **remove()**方法直接删除队头的元素:
**peek()**方法直接取出队头的元素,并不删除.
**element()**方法对peek方法进行简单封装,如果队头元素存在则取出并不删除,如果不存在抛出异常NoSuchElementException()
**poll()**方法取出并删除队头的元素,当队列为空,返回null
**take()**方法取出并删除队头的元素,当队列为空,则会一直等待直到队列有新元素可以取出,或者线程被中断抛出异常
1 | package com.zhangrui.sort; |
(2)针对Top K最有效的算法是BFPRT算法(中位数的中位数算法)
将n个元素每5个分为一组,分为n/5组,最后一组元素为n%5,有效组为n/5.
取出每一组的中位数,最后一个组的不用计算中位数,任意排序方法
将各组的中位数与数组开头的数据在组的顺序依次交换,这样每组的中位数就排在了每组数据的最左边
‘递归调用中位数选择算法查找出所有中位数的中位数,设为X,偶数个中位数的情况下设定为选取中间小的一个
按照X大小划分,大于或等于X的在X右边,小于X放在X左边
得到X元素的下标i,i左边的元素都小于X,i右边的元素都大于或等于X
若i==k,返回X
若i<k,在小于X元素中递归查找第i小的元素
若i>k,在大于等于X元素中递归查找第i-k小的元素
1 | package com.zhangrui.sort; |