寻找N个元素中最大的K个元素解法

来源:互联网 发布:重庆软件测试招聘 编辑:程序博客网 时间:2024/05/18 01:38

问题: 给定N个元素,寻找N个元素中最大的K个元素?

具体解法的算法思想就不详细解答了,详见《编程之美》第140页,下面给出几种解法的Java代码:

解法一:小顶堆原理

/** * 描述: 使用小顶堆来找出n个元素中,最大的k个;结果存放在[1...k],第0个元素位置不用; * * @param array * @param k */public static <T extends Comparable<T>> void heapKmax(T[] array, int k){// 建立K个元素的小顶堆, 元素从1到kfor(int i=k/2; i>0; i--){minHeapAdjust(array, i, k);}T temp;// 对于剩余的元素放入K个元素的小顶堆中for(int i=k+1; i<array.length; i++){if(array[1].compareTo(array[i])<0){temp = array[1];array[1] = array[i];array[i] = temp;minHeapAdjust(array, 1, k);}}}/** * 描述: 小顶堆筛选过程; * * @param array * @param root * @param limit */public static <T extends Comparable<T>> void minHeapAdjust(T[] array, int root, int limit){T tempRoot = array[root];for(int pos = 2*root; pos<=limit; pos*=2){if(pos<limit && array[pos].compareTo(array[pos+1])>0) pos++;if(tempRoot.compareTo(array[pos])<=0){break;}else{array[root] = array[pos];root = pos;}}array[root] = tempRoot;}
测试代码:

@Testpublic void testHeapSort(){Integer[] array = new Integer[] {0, 5, 10, 20, 1, 2, 23, -1, 22, 88, 77, 3 };System.out.println("----------排序前--------");for(int i=1; i<array.length; i++){System.out.print(array[i]+"\t");}System.out.println("\n----------排序后--------");heapSort(array);for(int i=1; i<array.length; i++){System.out.print(array[i]+"\t");}}

解法二: 类似快排序;

代码:

private static <T extends Comparable<T>> int partition(T[] array, int low,int high) {T pivot = array[low];while (low < high) {while (low < high && array[high].compareTo(pivot) >= 0) {high--;}if (low < high) {array[low] = array[high];low++;}while (low < high && array[low].compareTo(pivot) <= 0) {low++;}if (low < high) {array[high] = array[low];high--;}}array[low] = pivot;return low;}public static <T extends Comparable<T>> int kmax(T[] array, int start, int end, int k) {if(end-start+1<=k){return start;}if(start<end){int pos = partition(array, start, end);int num = end-pos+1;if(num == k){return pos;}else if(num > k){return kmax(array, pos+1, end, k);}else{return kmax(array, start, pos-1, k-num);}}else{return start;}}
测试代码:

@Testpublic void testKmax(String[] args) {Integer[] array = new Integer[] {0, 5, 10, 20, 1, 2, 23, -1, 22, 88, 77, 3 };int pos = kmax(array, 0, array.length-1, 7);for(int i=pos; i<array.length; i++){System.out.print(array[i]+"\t");}System.out.println();quickSort(array, 0, array.length-1);for(int i=0; i<array.length; i++){System.out.print(array[i]+"\t");}}

解法三: 类似二分查找;

代码:

public static int[] binaryKmax(int[] array, int k){int[] kArray = new int[k];// get max & minint max=array[0], min=array[0];for(int i=1; i<array.length; i++){if(array[i]>max){max = array[i];}if(array[i]<min){min = array[i];}}// binary search k max elementint mid = max, m;while(max>=min){mid = min + (int)((max-min)*0.5);m = mMax(array, mid, max);if(m == k){break;}else if(m>k){min = mid+1;}else{max = mid-1;k -= m;}}// get k elementsfor(int i=0, size=0; i<array.length; i++){if(array[i]>=mid){kArray[size++]=array[i];}}return kArray;}/** * 描述:找出[min,max]区间比key不小于key的值的个数;  * * @param array * @param key * @param max * @return */private static int mMax(int[] array, int key, int max){int count = 0;for(int i=0; i<array.length; i++){if(array[i]<=max && array[i]>=key){count++;}}return count;}

测试代码:

@Testpublic void testBinaryKmax(){int[] array = new int[] {1, 5, 10, 20, 1, 2, 23, -1, 22, 88, 77, 3 };System.out.println("----------排序前--------");for(int i=0; i<array.length; i++){System.out.print(array[i]+"\t");}System.out.println("\n----------排序后--------");int[] result = binaryKmax(array, 6);for(int i=0; i<result.length; i++){System.out.print(result[i]+"\t");}}


原创粉丝点击