java TopK算法

现有一亿个数据,要求从其中找出最小的一万个数,希望所需的时间和空间最小,也就是所谓的topK问题

TopK问题就是从海量的数据中取最大(或最小的)的K个数。

TopK问题其实是有线性时间复杂度的解的,在这里不作赘述

我使用的是堆排序方案,即维护一个大小为k的最小堆,遍历剩余的所有数据,并依次和堆顶元素比较,若其大于堆顶元素,则将其与堆顶元素互换,最终得到的堆即使所求。

java代码:

    /**
     * TopK算法,从一个数组中挑出最大的k个元素,如果第k个元素存在相等的,则只取靠前的
     * @param data 数据源,其元素必须实现Comparable接口
     * @param k
     * @return 长度为k的一个数组,储存的是符合条件的元素在data中的下标位置
     */
    public static <T extends Comparable<T>> int[] topK(T[] data,int k){
        if (k>=data.length){
            int[] temp=new int[data.length];
            for(int i=0;i<data.length;i++)
                temp[i]=i;
            return temp;
        }
        Heap<Ele<T>> heap=new MinHeapImpl<Ele<T>>();
        for(int i=0;i<k;i++){
            heap.add(new Ele<T>(data[i], i));
        }
        for(int i=k;i<data.length;i++){
            if (data[i].compareTo(heap.element().t)>0){
                heap.remove();
                heap.add(new Ele<T>(data[i],i));
            }
        }
        int[] temp=new int[k];
        int i=0;
        for(Ele<T> ele:heap){
            temp[i]=ele.index;
            i++;
        }
        return temp;
    }

节点类:

class Ele<T extends Comparable<T>> implements Comparable<Ele<T>>{
    T t;
    int index;
    /* (非 Javadoc)
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    @Override
    public int compareTo(Ele<T> o) {
        // TODO 自动生成的方法存根
        return t.compareTo(o.t);
    }
    public Ele(T t,int index){
        this.t=t;
        this.index=index;
    }
}

关于堆的构建在我的另一片随笔里有提到

原文地址:https://www.cnblogs.com/liujinming/p/8690339.html