1 问题描述
有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低。

2 解决方案
2.1 全部排序法

先对这n个整数进行快速排序,在依次输出前k个数。

package com.liuzhen.array_2;public class SearchMinK {//方法1:全部排序public void quickSort(int[] A,int start,int end){if(end > start){int k = LomutoPartition(A,start,end);quickSort(A,start,k-1);quickSort(A,k+1,end);}}//返回数值result,满足:     左边部分< A[result] <=右边部分public int LomutoPartition(int[] A,int start,int end){if(start >= end)return start;int begin = A[start];int result = start;for(int i = start + 1;i <= end;i++){if(A[i] < begin){result++;swap(A,i,result);}}swap(A,start,result);return result;}//交换数组m位置和n位置上的值public void swap(int[] arrayA,int m,int n){int temp = arrayA[m];arrayA[m] = arrayA[n];arrayA[n] = temp;}//输出数组前k个元素public void printArrayK(int[] array,int k){for(int i = 0;i < k;i++){System.out.print(array[i]+" ");}}
public static void main(String[] args){SearchMinK test = new SearchMinK();int[] A = {9,8,7,5,4,3,2,1,6,3,4,5,12,32,3,2,1,4,6,34};test.quickSort(A, 0, A.length-1);System.out.println("对数组进行排序后结果:");for(int i = 0;i < A.length;i++)System.out.print(A[i]+" ");System.out.println("\n"+"输出数组最小的5个数:");test.printArrayK(A, 5);}
}

运行结果:

对数组进行排序后结果:
1 1 2 2 3 3 3 4 4 4 5 5 6 6 7 8 9 12 32 34
输出数组最小的5个数:
1 1 2 2 3

2.2 部分排序法
具体操作步骤如下:

(1)遍历n个数,把最先遍历到的k个数存入到大小为k的数组中,假设他们就是最小的k个数;

(2)利用选择排序或交换排序找到这k个元素中的最大值kmax;

(3)继续遍历剩余的n-k个数。假设每次遍历到的新元素的值为x,把x与kmax进行比较:如果x<kmax,则用x替换kmax,并回到第2步重新找出k个元素的数组中新的最大元素kmax;如果x>=kmax,则继续遍历,不更新数组。

具体代码如下:

package com.liuzhen.array_2;public class SearchMinK {
//方法2:部分排序public void getArrayMinK(int[] A,int k){if(k > A.length)return;while(true){int max = getMaxArrayK(A,k);  //当前数组前k个元素中的最大值int count = 0;for(int i = k;i < A.length;i++){if(A[max] > A[i])swap(A,max,i);elsecount++;}if(count == A.length-k)break;}System.out.println("\n"+"使用方法2进行部分排序后的结果:");for(int i = 0;i < A.length;i++)System.out.print(A[i]+" ");System.out.println("\n部分排序选出数组中最小的"+k+"个数:");for(int i = 0;i < k;i++)System.out.print(A[i]+" ");}//获取数组前k个元素的最大值的数组下标public int getMaxArrayK(int[] A,int k){int result = 0;if(k > A.length)return 0;for(int i = 0;i < k;i++){if(A[i] > A[result])result = i;}return result;}
//交换数组m位置和n位置上的值public void swap(int[] arrayA,int m,int n){int temp = arrayA[m];arrayA[m] = arrayA[n];arrayA[n] = temp;}
public static void main(String[] args){SearchMinK test = new SearchMinK();int[] B = {9,8,7,5,4,3,2,1,6,3,4,5,12,32,3,2,1,4,6,34};test.getArrayMinK(B, 5);}

运行结果:

使用方法2进行部分排序后的结果:
1 1 2 2 3 9 8 7 6 5 4 5 12 32 4 3 3 4 6 34
部分排序选出数组中最小的5个数:
1 1 2 2 3

2.3 用堆代替数组法
此处思想和2.2中一致,唯一区别就是在寻找kmax时,是使用堆排序的思想。

具体代码如下:

package com.liuzhen.array_2;public class SearchMinK {
//方法3:用堆来代替数组/** 函数功能:对数组A前k个元素进行堆排序*/public void heapBottomUp(int[] A,int k){for(int i = (k-1)/2;i >= 0;i--){int temp = i;int tempV = A[temp];boolean heap = false;while(!heap && 2*temp < k-1){int j = 2*temp + 1;if(j < k-1){if(A[j] < A[j+1])j = j + 1;}if(tempV >= A[j])heap = true;else{A[temp] = A[j];temp = j;}}A[temp] = tempV;}}public void getArrayMinK2(int[] A,int k){heapBottomUp(A,k);while(true){int count = 0;for(int i = k;i < A.length;i++){if(A[i] < A[0]){swap(A,i,0);heapBottomUp(A,k);}elsecount++;}if(count == A.length-k)break;}System.out.println("\n"+"使用方法3进行部分堆排序后的结果:");for(int i = 0;i < A.length;i++)System.out.print(A[i]+" ");System.out.println("\n部分排序选出数组中最小的"+k+"个数:");for(int i = 0;i < k;i++)System.out.print(A[i]+" ");}
//交换数组m位置和n位置上的值public void swap(int[] arrayA,int m,int n){int temp = arrayA[m];arrayA[m] = arrayA[n];arrayA[n] = temp;}
public static void main(String[] args){SearchMinK test = new SearchMinK();int[] D = {9,8,7,5,4,3,2,1,6,3,4,5,12,32,3,2,1,4,6,34};test.getArrayMinK2(D, 5);}
}

运行结果:

使用方法3进行部分堆排序后的结果:
3 2 2 1 1 9 8 7 6 5 4 5 12 32 4 3 3 4 6 34
部分排序选出数组中最小的5个数:
3 2 2 1 1

2.4线性选择算法
看具体代码即可理解其中蕴含的思想。

package com.liuzhen.array_2;public class SearchMinK {
//返回数值result,满足:     左边部分< A[result] <=右边部分public int LomutoPartition(int[] A,int start,int end){if(start >= end)return start;int begin = A[start];int result = start;for(int i = start + 1;i <= end;i++){if(A[i] < begin){result++;swap(A,i,result);}}swap(A,start,result);return result;}//方法4:线性选择法public void getArrayMinK3(int[] A,int k){int start = 0;int end = A.length - 1;int tempK = LomutoPartition(A,start,end);while(tempK != k){if(tempK > k){end = tempK - 1;tempK = LomutoPartition(A,start,end);}if(tempK < k){start = tempK + 1;tempK = LomutoPartition(A,start,end);}}System.out.println("\n"+"使用方法4进行快速选择排序后的结果:");for(int i = 0;i < A.length;i++)System.out.print(A[i]+" ");System.out.println("\n部分排序选出数组中最小的"+k+"个数:");for(int i = 0;i < k;i++)System.out.print(A[i]+" ");}
public static void main(String[] args){SearchMinK test = new SearchMinK();int[] E = {9,8,7,5,4,3,2,1,6,3,4,5,12,32,3,2,1,4,6,34};test.getArrayMinK3(E, 5);}
}

运行结果:

使用方法4进行快速选择排序后的结果:
1 2 2 1 3 3 3 4 5 5 4 4 6 8 6 7 9 32 12 34
部分排序选出数组中最小的5个数:
1 2 2 1 3

此处附上四种方法的完整代码

package com.liuzhen.array_2;public class SearchMinK {//方法1:全部排序public void quickSort(int[] A,int start,int end){if(end > start){int k = LomutoPartition(A,start,end);quickSort(A,start,k-1);quickSort(A,k+1,end);}}//返回数值result,满足:     左边部分< A[result] <=右边部分public int LomutoPartition(int[] A,int start,int end){if(start >= end)return start;int begin = A[start];int result = start;for(int i = start + 1;i <= end;i++){if(A[i] < begin){result++;swap(A,i,result);}}swap(A,start,result);return result;}//交换数组m位置和n位置上的值public void swap(int[] arrayA,int m,int n){int temp = arrayA[m];arrayA[m] = arrayA[n];arrayA[n] = temp;}//输出数组前k个元素public void printArrayK(int[] array,int k){for(int i = 0;i < k;i++){System.out.print(array[i]+" ");}}//方法2:部分排序public void getArrayMinK(int[] A,int k){if(k > A.length)return;while(true){int max = getMaxArrayK(A,k);  //当前数组前k个元素中的最大值int count = 0;for(int i = k;i < A.length;i++){if(A[max] > A[i])swap(A,max,i);elsecount++;}if(count == A.length-k)break;}System.out.println("\n"+"使用方法2进行部分排序后的结果:");for(int i = 0;i < A.length;i++)System.out.print(A[i]+" ");System.out.println("\n部分排序选出数组中最小的"+k+"个数:");for(int i = 0;i < k;i++)System.out.print(A[i]+" ");}//获取数组前k个元素的最大值的数组下标public int getMaxArrayK(int[] A,int k){int result = 0;if(k > A.length)return 0;for(int i = 0;i < k;i++){if(A[i] > A[result])result = i;}return result;}//方法3:用堆来代替数组/** 函数功能:对数组A前k个元素进行堆排序*/public void heapBottomUp(int[] A,int k){for(int i = (k-1)/2;i >= 0;i--){int temp = i;int tempV = A[temp];boolean heap = false;while(!heap && 2*temp < k-1){int j = 2*temp + 1;if(j < k-1){if(A[j] < A[j+1])j = j + 1;}if(tempV >= A[j])heap = true;else{A[temp] = A[j];temp = j;}}A[temp] = tempV;}}public void getArrayMinK2(int[] A,int k){heapBottomUp(A,k);while(true){int count = 0;for(int i = k;i < A.length;i++){if(A[i] < A[0]){swap(A,i,0);heapBottomUp(A,k);}elsecount++;}if(count == A.length-k)break;}System.out.println("\n"+"使用方法3进行部分堆排序后的结果:");for(int i = 0;i < A.length;i++)System.out.print(A[i]+" ");System.out.println("\n部分排序选出数组中最小的"+k+"个数:");for(int i = 0;i < k;i++)System.out.print(A[i]+" ");}//方法4:线性选择法public void getArrayMinK3(int[] A,int k){int start = 0;int end = A.length - 1;int tempK = LomutoPartition(A,start,end);while(tempK != k){if(tempK > k){end = tempK - 1;tempK = LomutoPartition(A,start,end);}if(tempK < k){start = tempK + 1;tempK = LomutoPartition(A,start,end);}}System.out.println("\n"+"使用方法4进行快速选择排序后的结果:");for(int i = 0;i < A.length;i++)System.out.print(A[i]+" ");System.out.println("\n部分排序选出数组中最小的"+k+"个数:");for(int i = 0;i < k;i++)System.out.print(A[i]+" ");}public static void main(String[] args){SearchMinK test = new SearchMinK();int[] A = {9,8,7,5,4,3,2,1,6,3,4,5,12,32,3,2,1,4,6,34};test.quickSort(A, 0, A.length-1);System.out.println("对数组进行排序后结果:");for(int i = 0;i < A.length;i++)System.out.print(A[i]+" ");System.out.println("\n"+"输出数组最小的5个数:");test.printArrayK(A, 5);int[] B = {9,8,7,5,4,3,2,1,6,3,4,5,12,32,3,2,1,4,6,34};test.getArrayMinK(B, 5);int[] C = {2,9,7,6,5,8};test.heapBottomUp(C, 6);System.out.println("\nC数组:");for(int i = 0;i < C.length;i++)System.out.print(C[i]+" ");int[] D = {9,8,7,5,4,3,2,1,6,3,4,5,12,32,3,2,1,4,6,34};test.getArrayMinK2(D, 5);int[] E = {9,8,7,5,4,3,2,1,6,3,4,5,12,32,3,2,1,4,6,34};test.getArrayMinK3(E, 5);}
}完整代码

Java实现寻找最小的k个数相关推荐

  1. 海量数据中,寻找最小的k个数。

    维护k个元素的最大堆,即用容量为k的最大堆存储最小的k个数,k1设为大顶堆中最大元素.遍历一次数列,n,每次遍历一个元素x,与堆顶元素比 较,x<kmax,更新堆,否则不更新堆. 1 // 海量 ...

  2. 程序员编程艺术:第三章、寻找最小的k个数

    程序员编程艺术:第三章.寻找最小的k个数 作者:July. 时间:二零一一年四月二十八日. 致谢:litaoye, strugglever,yansha,luuillu,Sorehead,及狂想曲创作 ...

  3. c语言从4个整数中找最小的数,编程之法:面试和算法心得(寻找最小的k个数)...

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 输入n个整数,输出其中最小的k个. 分析与解法 解法一 要求一个序列中最小的k个数,按照惯有的思维方式,则是先对这个 ...

  4. java第k大的数字,JAVA中寻找最大的K个数解法

    这个题拿到之后首先会想到排序,排好序之后在选取选取最大的K个数.排序选择快速排序是个比较好的选择. 好了,让我们来进行第一个解法:快速排序 代码如下 复制代码代码如下: public static v ...

  5. 寻找数组中最小的k个数(快排和堆排)

    题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 思路1:利用快排的思想,寻找第k个位置上正确的数,k位置前面的数即 ...

  6. 伍六七带你学算法 入门篇-最小的k个数

    java面试题-最小的k个数 难度-简单 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:a ...

  7. 微软编程题:寻找最小的k个值

    转载自:http://blog.csdn.net/v_JULY_v/article/details/6370650 寻找最小的k个数 题目描述:5.查找最小的k个元素 题目:输入n个整数,输出其中最小 ...

  8. [剑指offer][JAVA][面试第40题][最小的k个数][快选][堆][BST]

    [问题描述]面试第40题 最小的k个数 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 : 输入:arr ...

  9. 46最小的k个数 47寻找第k大

    46 最小的k个数 第一反应排序的话是O(nlogn),暴力是O(NK),看了题解用优先队列,因为优先队列插入元素需要logn,我们只要让堆的大小控制在k,插入一个元素就值需要logk,这样整体的时间 ...

最新文章

  1. MXNet 安装 Windows
  2. Javascript中的日期函数[zz]
  3. Linux arp相关命令(地址解析协议)
  4. 前端后分离深入分析 ——浏览器渲染和服务器渲染区别
  5. python正则匹配所有的中文,数字和英文
  6. JSON.parse和JSON.stringify方法
  7. 中高级PHP程序员应该掌握哪些技术
  8. mysql启动找不见socket
  9. php读取excel文件_PHP读取Excel类文件
  10. 简单 Quartz定时器使用 入门
  11. 光学变焦----景深=景深远界-景深近界
  12. 华为路由器命令手册_用数据说话,华为路由Q2 Pro与网件R7800对比测评
  13. 中国电信北京研究院副院长陈运清:网络云化推进中技术和商业驱动场景探讨...
  14. 【Python】利用zipfile.ZipFile和write()创建压缩包
  15. STM32_温湿度传感器
  16. c语言平台答案,C语言平台答案.docx
  17. 软件开发人员绩效评价标准
  18. 哈佛经理人自我激励自我超越艺术
  19. 回顾历史_回顾美联储历史,美国货币政策是如何演变的?
  20. OSError: [Errno 22] Invalid argument: 'E:\\DESK\x08ank dataset\train_set.csv'

热门文章

  1. linux下的"BusHound"——usbmon
  2. 河南专升本2018年高等数学真题
  3. GSM模块_PDU中文格式发送短信息
  4. 让在线测试仪真正发挥作用
  5. 关于h5网站常用的样式设置
  6. php-fpm upstream,nginx 通过upstream实现与多个php-fpm进程通信
  7. pandas 多折线图_干货:使用pandas和seaborn制作炫酷图表(附代码)
  8. TCP/IP实现(十) 协议控制块
  9. 高一计算机课学了哪些知识,高一信息技术课教学计划
  10. ONOS编程系列(一)之简单应用开发