1. 程式人生 > >經典算法(一) top k

經典算法(一) top k

出現次數 有序數組 取出 數量 歸並 個數 維護 如果 大小

問題:1億數據中,找出最大的k個數,要求使用內存不超過1m

(延伸問題:1億數據中,找出重復出現次數最多的k個,要求使用內存不超過1m)

分析:

1億數字(int)占內存:100000000 * 4byte / 1024 / 1024 =381m

其中 int=4byte,1m=1024kb,1kb=1024b

實現:

維護一個k大小的數組有序數組。每次加進來新的,都要判斷是不是 換掉 該數組中最小的元素,如果需要,則刪除最小元素,放入新元素,並重新排序。

基於小頂堆的實現:

創建一個k大小的堆。TOP K堆只用維護固定數量的元素,每次加進來新的,都要判斷是否替換掉堆頂元素,如果需要,則刪除堆頂元素,放入新元素,並重新構造堆

public class TopK_ByHeapSort {
    
    //向小頂堆插入一個新的元素
    public static void insertHeap(int[] heap, int value) {
        heap[0] = value;
        adjustHeap(heap, 0, heap.length);// 重新對堆進行調整
    }

    //調整堆
    public static void adjustHeap(int[] arr, int i, int length) {
        int temp = arr[i];// 先取出當前元素i
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {// 從i結點的左子結點開始,也就是2i+1處開始 if (k + 1 < length && arr[k] > arr[k + 1]) {// 如果左子結點小於右子結點,k指向右子結點 k++; } if (arr[k] < temp) {// 如果子節點小於父節點,將子節點值賦給父節點(不用進行交換) arr[i] = arr[k]; i
= k; } else { break; } } arr[i] = temp;// 將temp值放到最終的位置 } //構建小頂堆 public static void createMinHeap(int[] arr){ for (int i = arr.length / 2 - 1; i >= 0; i--) { adjustHeap(arr, i, arr.length); } } //交換元素 public static void swap(int[] arr, int a, int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } //將小頂堆 轉化為 有序數組 public static int[] minHeapToSortArr(int[] arr){ for (int j = arr.length - 1; j > 0; j--) { swap(arr, 0, j);// 將堆頂元素與末尾元素進行交換 adjustHeap(arr, 0, j);// 重新對堆進行調整 } return arr; } public static void print(int[] n) { for (int i = 0; i < n.length; i++) { System.out.print(" " + n[i]); } System.out.println(); } //使用堆排序實現topk public static int[] getTopKByHeap(int input[], int k) { //構建k大小數組 int[] result = new int[k]; for (int i = 0; i < k; i++) result[i] = input[i]; //構建小頂堆 createMinHeap(result); //將新元素插入小頂堆 for (int i = k; i < input.length; i++) { if (input[i] > result[0]) insertHeap(result, input[i]); // 復雜度最壞是O(nlgK),而且內存消耗就K,不然海量數據排序,內存放不下,得用歸並排序,最好最壞平均都是 } //將小頂堆轉化為有序數組 minHeapToSortArr(result); return result; } public static void main(String[] args) { int input[] = { 37, 3, 5, 29, 2, 9, 10, 40, 99 }; int k=6; print(getTopKByHeap(input, k)); } }

經典算法(一) top k