题目:求海量数据(正整数)按逆序排列的前k个数(topK),因为数据量太大,不能全部存储在内存中,只能一个一个地从磁盘或者网络上读取数据,请设计一个高效的算法来解决这个问题。 第一行用户输入K,代表要求得topK 随后的N(不限制)行,每一行是一个整数代表用户输入的数据 直到用户输入-1代表输入终止 请输出topK,空格分割。
思路:先开辟一个K大小的数组arr,然后读取K个数据存储到数组arr,读到K+1的时候,如果arr[K+1]小于arr中最小的值,那么就丢掉不管,如果arr[K+1]大于arr中最小的值,那么就把arr[K+1]和数组中最小的值进行交换,然后再读取K+2个数。这样就能解决这个问题。但是这个算法复杂度为K+(N-K)*K,K可以忽略不计,所以时间复杂度为O(KN)。那这个代码很容易就写出来。假如题目要求用到NlgK的时间复杂度,那么这里就需要使用堆这种数据结构来解决问题,而且还是小顶堆。具体思想还是和数组一样。
代码:
1 import java.util.Arrays; 2 import java.util.Scanner; 3 4 public class TopK { 5 6 static int[] heap; 7 static int index = 0; 8 static int k; 9 10 public static void main(String[] args) { 11 Scanner scanner = new Scanner(System.in); 12 k = scanner.nextInt(); 13 heap = new int[k]; 14 int x = scanner.nextInt(); 15 while(x!=-1){ 16 deal(x); // 处理x 17 x = scanner.nextInt(); 18 } 19 System.out.println(Arrays.toString(heap)); 20 } 21 22 /** 23 * 如果数据量小于等于k,直接加入堆中 24 * 等于k的时候,进行堆化 25 * @param x 26 */ 27 private static void deal(int x) { 28 if (index<k) { 29 heap[index++] = x; 30 if (index==k) { 31 // 堆化 32 makeMinHeap(heap); 33 System.out.println(Arrays.toString(heap)); 34 } 35 }else if (heap[0]<x) { 36 heap[0] = x; 37 MinHeapFixDown(heap, 0, k); 38 System.out.println(Arrays.toString(heap)); 39 }else { 40 System.out.println(Arrays.toString(heap)); 41 } 42 } 43 static void makeMinHeap(int[] A){ 44 int n = A.length; 45 for(int i = n/2-1;i>=0;i--){ 46 MinHeapFixDown(A,i,n); 47 } 48 } 49 50 private static void MinHeapFixDown(int[] A, int i, int n) { 51 // 找到左右孩子 52 int left = 2 * i + 1; 53 int right = 2 * i + 2 ; 54 // 左孩子已经越界,i就是叶子节点 55 if (left>=n) { 56 return ; 57 } 58 // min 指向了左右孩子中较小的那个 59 int min = left; 60 if (right>=n) { 61 min = left; 62 }else { 63 if (A[right]<A[left]) { 64 min = right; 65 } 66 } 67 // 如果A[i]比两个孩子都要小,不用调整 68 if (A[i]<=A[min]) { 69 return ; 70 } 71 // 否则,找到两个孩子中较小的,和i交换 72 int temp = A[i]; 73 A[i] = A[min]; 74 A[min] = temp; 75 // 小孩子那个位置的值发生了变化,i变更为小孩子那个位置,递归调整 76 MinHeapFixDown(A, min, n); 77 } 78 79 }
结果:
总结:partition和堆都能解决顺序统计量问题,堆更适用于海量数据流,适用于不能全部存储在内存中的数据,相当于实时数据流,而partition适用于能够一次加载到内存的数组。
原文地址:https://www.cnblogs.com/xiaoyh/p/10290040.html
时间: 2024-10-25 12:44:41