Top k問題的討論(三種方法的java實現及適用範圍)

在不少的筆試和麪試中,喜歡考察Top K.下面從自身的經驗給出三種實現方式及實用範圍。java

  • 合併法

    這種方法適用於幾個數組有序的狀況,來求Top k。時間複雜度爲O(k*m)。(m:爲數組的個數).具體實現以下:面試

/**
* 已知幾個遞減有序的m個數組,求這幾個數據前k大的數
*適合採用Merge的方法,時間複雜度(O(k*m);
*/
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
public class TopKByMerge{
 public int[] getTopK(List<List<Integer>>input,int k){
    int index[]=new int[input.size()];//保存每一個數組下標掃描的位置;
    int result[]=new int[k];
    for(int i=0;i<k;i++){
       int max=Integer.MIN_VALUE;
       int maxIndex=0;
       for(int j=0;j<input.size();j++){
           if(index[j]<input.get(j).size()){
                if(max<input.get(j).get(index[j])){
                    max=input.get(j).get(index[j]);
                    maxIndex=j;
                }
           }
       }
       if(max==Integer.MIN_VALUE){
           return result;
       }
       result[i]=max;
       index[maxIndex]+=1;
       
    }
    return result;
 } 
  •  快排過程法

    快排過程法利用快速排序的過程來求Top k.平均時間複雜度爲(O(n)).適用於無序單個數組。具體java實現以下:數組

/*
*利用快速排序的過程來求最小的k個數
*
*/
public class TopK{
   int partion(int a[],int first,int end){
        int i=first;
        int main=a[end];
        for(int j=first;j<end;j++){
             if(a[j]<main){
                int temp=a[j];
                a[j]=a[i];
                a[i]=temp;
                i++;
             }
        }
        a[end]=a[i];
        a[i]=main;
        return i;    
   }
   void getTopKMinBySort(int a[],int first,int end,int k){
      if(first<end){
          int partionIndex=partion(a,first,end);
          if(partionIndex==k-1)return;
          else if(partionIndex>k-1)getTopKMinBySort(a,first,partionIndex-1,k);
          else getTopKMinBySort(a,partionIndex+1,end,k);
      }
   }
public static void main(String []args){
      int a[]={2,20,3,7,9,1,17,18,0,4};
      int k=6;
      new TopK().getTopKMinBySort(a,0,a.length-1,k);
      for(int i=0;i<k;i++){
         System.out.print(a[i]+" ");
      }
   }
}
  • 採用小根堆或者大根堆

   求最大K個採用小根堆,而求最小K個採用大根堆。大數據

  求最大K個的步奏:this

  1.     根據數據前K個創建K個節點的小根堆。
  2.     在後面的N-K的數據的掃描中,
  • 若是數據大於小根堆的根節點,則根節點的值覆爲該數據,並調節節點至小根堆。
  • 若是數據小於或等於小根堆的根節點,小根堆無變化。

 求最小K個跟這求最大K個相似。時間複雜度O(nlogK)(n:數據的長度),特別適用於大數據的求Top K。spa

/**
 * 求前面的最大K個 解決方案:小根堆 (數據量比較大(特別是大到內存不能夠容納)時,偏向於採用堆)
 * 
 * 
 */
public class TopK {
    /**
     * 建立k個節點的小根堆
     * 
     * @param a
     * @param k
     * @return
     */
    int[] createHeap(int a[], int k) {
        int[] result = new int[k];
        for (int i = 0; i < k; i++) {
            result[i] = a[i];
        }
        for (int i = 1; i < k; i++) {
            int child = i;
            int parent = (i - 1) / 2;
            int temp = a[i];
            while (parent >= 0 &&child!=0&& result[parent] >temp) {
                result[child] = result[parent];
                child = parent;
                parent = (parent - 1) / 2;
            }
            result[child] = temp;
        }
        return result;

    }

    void insert(int a[], int value) {
         a[0]=value;
         int parent=0;
         
         while(parent<a.length){
             int lchild=2*parent+1;
             int rchild=2*parent+2;
             int minIndex=parent;
             if(lchild<a.length&&a[parent]>a[lchild]){
                 minIndex=lchild;
             }
             if(rchild<a.length&&a[minIndex]>a[rchild]){
                 minIndex=rchild;
             }
             if(minIndex==parent){
                 break;
             }else{
                 int temp=a[parent];
                 a[parent]=a[minIndex];
                 a[minIndex]=temp;
                 parent=minIndex;
             }
         }
         
    }

    int[] getTopKByHeap(int input[], int k) {
        int heap[] = this.createHeap(input, k);
        for(int i=k;i<input.length;i++){
            if(input[i]>heap[0]){
                this.insert(heap, input[i]);
            }
        
            
        }
        return heap;

    }

    public static void main(String[] args) {
        int a[] = { 4, 3, 5, 1, 2,8,9,10};
        int result[] = new TopK().getTopKByHeap(a, 3);
        for (int temp : result) {
            System.out.println(temp);
        }
    }
}
相關文章
相關標籤/搜索