一般看到寻找最大的k个数的题目,我们第一想法便是先使用降序排序,然后取前k个即可,这种方法确实是比较常规的,一般情况下也是可行的,但是如果数据十分庞大,则会影响使得创建的数组内存溢出等等。因此,需要对相关算法思路进行优化,以下是几种不同解法。通过不同解法比较从而更理解该算法题。

1.简单排序法

从n个数中直接先排序,然后求最大的k个,从而获取最大的k个数。代码如下:

package knum;
import java.util.*;
public class GeneralSort {public static void main(String[] args){Scanner sc=new Scanner(System.in);int n=sc.nextInt();int k=sc.nextInt();int[] data=new int[n];for(int i=0;i<n;i++)data[i]=sc.nextInt();Arrays.sort(data);for(int j=0;j<k-1;j++){System.out.print(data[--n]+" ");}System.out.print(data[--n]);}}

测试结果如下:

10 3
1 5 7 4 8 20 2 15 9 10
20 15 10

以上采用的是系统自带的排序,总的求解时间复杂度为O(n*logn+k),近似于O(n*logn)。至于排序可以换成快排或者归并排序来进行实现。

2.创建最小堆实现

以上是对所有数据都进行排序,则进行排序的数据的量可能非常大,如果k的值远小于n,则会影响效率。因此,可以借鉴堆排序的方法,通过维护最小堆来进行保留k个最大值。该方法的思路是:首先先读取k个数字,对这k个数字进行创建最小堆,将最小的数放到堆顶,然后再读取第k+1个数,比较堆顶与该值,取较大值。然后重复上述的操作,留下最后k个数即为需要求的k个最大值。时间复杂度为O(nlogk)。这种方法好处在于不必担心数组内存的溢出以及时间复杂度较一般排序法也能稍作优化。实现代码如下:

package knum;
import java.util.*;
public class HeapSort {  public static void swap(int[] data,int i,int j)  {  if(i==j)  return;  data[i]=data[i]+data[j];  data[j]=data[i]-data[j];  data[i]=data[i]-data[j];  }  public static int[] heapSort(int[] data,int[] A,int k)  {  for(int i=0;i<A.length-k;i++)//控制堆大小。  {  //每次遍历创建最小堆,并且将堆顶元素与给定数组的数字按序逐个比较,若小于相应元素,则替换堆顶元素。  createMinHeap(data,k-1);//堆化  if(data[0]<A[k+i])data[0]=A[k+i];print(data);  }  return data;  }  public static void createMinHeap(int[] data,int lastIndex)  {  for(int i=(lastIndex-1)/2;i>=0;i--)  //先找到最后一个节点的双亲节点,然后依次往回遍历,{                                    //并在过程中重新访问当前节点的子节点,目的就是将最小值移到双亲位置,依次往上,直到最小值到达堆顶//保存当前正在判断的节点  int k=i;  //若当前节点存在  while(2*k+1<=lastIndex)  {  //smallerIndex总是记录较小节点的值,先赋值为当前判断节点的左子节点  int smallerIndex=2*k+1;  if(smallerIndex<lastIndex) //判断是否存在右子节点{  //若右子节点存在,否则此时smallerIndex应该等于lastIndex  if(data[smallerIndex]>data[smallerIndex+1])  {  //若右子节点值比左子节点值小,则smallerIndex记录的是右子节点的值  smallerIndex++;  }  }  if(data[k]>data[smallerIndex])  {  //若当前节点值比子节点最小值大,则交换两者的值,交换后将smallerIndex值赋给k,相当于将最小值往堆顶推swap(data,k,smallerIndex);  k=smallerIndex;  }  else  break;  }  }  }  public static void print(int[] data)  {  for(int i=0;i<data.length;i++)  System.out.print(data[i]+" ");  System.out.println();  }  public static void main(String[] args)  {  Scanner sc=new Scanner(System.in);int n=sc.nextInt();int k=sc.nextInt();int[] A=new int[n];int[] data=new int[k];for(int j=0;j<n;j++){A[j]=sc.nextInt();}for(int j=0;j<k;j++){data[j]=A[j];}int[] ans=heapSort(data,A,k);  System.out.println("堆排序后的序列:");  for(int j=0;j<ans.length;j++)  System.out.print(ans[j]+" ");  }  }  

测试结果如下:

10 3
1 5 7 4 8 20 2 15 9 10
4 5 7
8 5 7
20 8 7
7 8 20
15 8 20
9 15 20
10 15 20
堆排序后的序列:
10 15 20 

算法题解之寻找最大的k个数相关推荐

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

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

  2. 编程之美2.5 寻找最大的K个数

    在一个数组中寻找最大的K个数,我们首先说一种非常简单的方法,利用快速排序中的分割算法,即我们经常看见的partition.这个函数会返回一个 int 类型的值,这个值代表的是前一半数字和后一半数字的分 ...

  3. 编程之美-寻找最大的k个数

    [问题描述] 有很多无序的数,我们姑且假定它们各不相等,怎么选出其中最大的若干个数呢? 方法一:时间复杂度min(O(nlogn), O(nk)) idea 1: 先用快速排序或者堆排序进行排序,然后 ...

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

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

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

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

  6. 寻找最大的k个数问题

    这是编程之美书第2.5节的一道题目. 各种解法: 解法一,用nlgn复杂度的排序算法对数组进行从大到小排序,取前K个.但这方法做了两件不必要做的事:它对想得到的K个数进行了排序,对不想得到的n-K个数 ...

  7. Java实现寻找最小的k个数

    1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 解决方案 2.1 全部排序法 先对这n个整数进行快速排序,在依次输出前k个数. package com.liuzhen. ...

  8. 寻找最大的K个数(上)

    这是一道很经典的题目,有太多方法了,今天写了两种方法,分别是快排和堆排序 1 #include <iostream> 2 using namespace std; 3 #define N ...

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

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

最新文章

  1. 理解CSS3 transform中的Matrix(矩阵)
  2. eclipse手动pom本地包_环境篇--Eclipse如何远程连接Hadoop集群调试
  3. AWS Lambda 开发企业微信消息机器人
  4. 赵雅智:service_startService生命周期
  5. 想提高用户访问的响应速度和成功率还不赶快学习CDN
  6. java环境一键配置下载地址_java环境一键配置-java环境一键配置下载 v1.0免费版-下载啦...
  7. 无法安装Visual Studio 2010 Service Pack 1
  8. VTK(五)---内窥镜漫游(基于VMTK血管中心线提取)
  9. WordPress中文SEO优化建议
  10. SAI:Switch Abstraction Interface
  11. WinForm界面控件DevExpress入门指南 - Window Service
  12. 疫情地图 | 低代码制作全国重点管控地区行政区地图(截至4月16日)
  13. 计算机竞赛制作机器人,2016全国中小学电脑制作比赛机器人灭火竞赛规则
  14. LTE资源调度(6)-功率余量报告PHR
  15. 4大主流CPU处理器技术架构详解
  16. 【BZOJ】3168: [Heoi2013]钙铁锌硒维生素
  17. 参考基因组 坐标转换 hg38 hg19
  18. 访问的网页自动打开QQ对话
  19. 连接mysql报错Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zon
  20. AminoCapital:大数据+机械学习引领今年硅谷趋势

热门文章

  1. 网络编程中Nagle算法和Delayed ACK的测试(转)
  2. 【apk破解尝试之旅】-——apk文件的反编译与回编译
  3. Exchange中的收件人类型区别--用户邮箱,邮件用户,邮件联系人
  4. 教室人数检测matlab代码,教室人数检测器.pdf
  5. android 微信绑定银行卡号,Android微信支付详细步骤
  6. 软件测试工作的必会的三个阶段!
  7. 编译lichee zero
  8. 全能赛道、热门方向、稀缺数据,不能错过的自动驾驶技术挑战赛
  9. linux cst utc时间转换,Linux下CST和UTC时间的区别以及不一致的解决方法
  10. [Andriod] fastboot 和 recovery 模式的区别