问题描写叙述:求一个数组的最大k个数。如,{1,5,8,9,11,2,3}的最大三个数应该是,8,9,11

问题分析:

1.解法一:最直观的做法是将数组从大到小排序,然后选出当中最大的K个数。可是这种解法,复杂度是O(logn*n),可是有时候并不须要排序,用简单的选择排序。或者是冒泡排序,那么就K轮的交换或者是选择。就能够得出结论,复杂度是O(n*k),当K非常大的时候排序可能是更好的解法。当K小的时候用选择或者是冒泡效率会更加的高。

可是这都是会对前K个数进行排序。所以效率不高。当K非常大的时候,以上两种方法效率都不是非常高。

2.解法二:不正确前K个数进行排序,回顾快排的算法中,那个partition函数。就是随机选择数组中的一个数。把比这个数大的数,放在数组的前面。把比这个数小的数放在数组的

后面,这时想假设找出的随机数。终于位置就是K,那么最大的K个数就找出来了,沿着这个思路思考问题。可是这个函数。最后的索引位置并不一定是K,可能比K大也可能比K小,我们把找出的数组分成两部分sa。sb,sa是大的部分,sb是小的部分,假设sa的长度等于K的话,那么直接返回就是终于结果,假设sa的长度要比K大的话,那么以sa为新的数组,从sa中找出K个最大的数。这时候就把原始数据集降低到的sa。假设sa的长度比K小的话,增加sa中有m个元素,那么m个元素算作是K中元素的一部分,再从sb中找到,k-m个最大的元素,组合起来就是终于的结果,那么这时把问题简化成从sb中找k-m个最大的元素,所以整体来说这是一个递归的过程,尽管复杂大也是O(n*logn)可是,每一次数据量都会降低所以会更加的快。

3.解法三:是利用堆排序,建立一个K阶最大堆,然后数据一个个插入队其中,那么插入队的时间复杂度是O(logK),适合数据量比較大的时候,用堆的效果更加好。

这里给出解法二的代码供大家參考:

public class Main {

	private static void swap(int[] nums,int index1,int index2){
int temp=nums[index1];
nums[index1]=nums[index2];
nums[index2]=temp;
} public static int partition(int[] nums,int start,int end){
int index=new Random().nextInt(nums.length);
int num=nums[index];
swap(nums, index, 0);
int i=start;
int j=end;
while(i<j){
while(i<j&&nums[j]<=num){
j--;
}
if(i<j){
nums[i++]=nums[j];
}
while(i<j&&nums[i]>num){
i++;
}
if(i<j){
nums[j--]=nums[i];
}
}
nums[i]=num;
return i;
} public static int partition(int[] nums){
return partition(nums, 0, nums.length-1); } public static int[] findKmax(int[] nums,int k,int start,int end){
int index=partition(nums,start,end);
int length=index-start+1;
int[] tempMax=Arrays.copyOf(nums, length);
int[] tempMin=new int[nums.length-length];
System.arraycopy(nums, index+1, tempMin, 0, nums.length-length);
if(length>k){
return findKmax(tempMax,k,0,tempMax.length-1);
}else if(length==k){
return tempMax;
}else{
int[] temp2=new int[k];
System.arraycopy(tempMax, 0, temp2, 0, tempMax.length);
int[] temp3=findKmax(tempMin,k-length,0,tempMin.length-1);
System.arraycopy(temp3,0, temp2, index+1, temp3.length);
return temp2;
}
} public static int[] findKmax(int[] nums,int k){
return findKmax(nums, k, 0, nums.length-1);
} public static void print(int[] nums){
for(int i=0;i<nums.length;i++){
System.out.print(nums[i]+" ");
}
} public static void main(String[] args) {
int[] nums={1,5,8,9,11,2,3};
int[] temp=findKmax(nums, 3);
System.out.println("ret:");
print(temp);
} }

求一个数组的最大k个数(java)的更多相关文章

  1. 求一个数组中第K小的数

    面试南大夏令营的同学说被问到了这个问题,我的第一反应是建小顶堆,但是据他说用的是快排的方法说是O(n)的时间复杂度, 但是后来经过我的考证,这个算法在最坏的情况下是O(n^2)的,但是使用堆在一般情况 ...

  2. 求一个数组中最小的K个数

    方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...

  3. JS求一个数组元素的最小公倍数

    求几个数的最小公倍数就是先求出前两个数的最小公倍数,然后再把这个最小公倍数跟第三个数放在一起来求最小公倍数,如此类推... var dbList = []; //两个数的最小公倍数 function ...

  4. HDU-1695 GCD(求一个区间内与一个数互质的个数)

    题意: 给你一个T,是样例的个数,接下来是五个数l1,r1,l2,r2,k  前四个数代表两个区间(l1,r1),(l2,r2)这个题l1=1,l2=1; 取x1属于(1,r1),x2属于(1,r2) ...

  5. 用递归的方法求一个数组的前n项和

    用递归的方法求一个数组的前n项和 public class Demo1 { /* * 用递归的方法求一个数组的前n项和 */ public static void main(String[] args ...

  6. 算法 - 求一个数组的最长递减子序列(C++)

    //************************************************************************************************** ...

  7. java二分法来求一个数组中一个值的key

    package TestArray; import java.util.Arrays; /** * 二分法查找 */ public class Test { public static void ma ...

  8. 剑指Offer:面试题30——最小的k个数(java实现)

    问题描述: 输入n个整数,找出其中最小的k个数 思路1: 先排序,再取前k个 时间复杂度O(nlogn) 下面给出快排序的代码(基于下面Partition函数的方法) public void Quic ...

  9. 获取一个数组里面第K大的元素

    如何在O(n)内获取一个数组比如{9, 1, 2, 8, 7, 3, 6, 4, 3, 5, 0, 9, 19, 39, 25, 34, 17, 24, 23, 34, 20}里面第K大的元素呢? 我 ...

随机推荐

  1. 【codeforces 767E】Change-free

    [题目链接]:http://codeforces.com/problemset/problem/767/E [题意] 你有m个1元硬币和无限张100元纸币; 你在第i天,需要花费ci元; 同时在第i天 ...

  2. java string遇到的一个奇葩bug

    String abc = "1"; HashMap<String, String> hMap = new HashMap<String, String>() ...

  3. POSIX 线程编程(一)简介

    简介 在共享内存的多处理器结构中,可以用线程来实现并行.对于UNIX系统, IEEE POSIX 1003.1c标准规定了C语言线程编程接口的标准.这份标准的实现就是POSIX threads, 或者 ...

  4. 怎样在Nginxserver中启用Gzip压缩

    原文链接: Enable GZIP Compression on nginx Servers原文日期: 2014年7月16日翻译日期: 2014年7月19日翻译人员: 铁锚 速度决定一切,没有什么比一 ...

  5. dotnet core test with NUnit

    https://github.com/nunit/dotnet-test-nunit if you are using Visual Studio. Your project.json in your ...

  6. ThinkPHP5.0框架开发--第4章 TP5.0路由

    ThinkPHP5.0框架开发--第4章 TP5.0路由 第4章 TP5.0 路由 ================================================== 上次复习 1. ...

  7. ElasticSearch 深入理解 三:集群部署设计

    ElasticSearch 深入理解 三:集群部署设计 ElasticSearch从名字中也可以知道,它的Elastic跟Search是同等重要的,甚至以Elastic为主要导向. Elastic即可 ...

  8. MetaSploit攻击实例讲解------攻击445端口漏洞(kali linux 2016.2(rolling))(详细)

    不多说,直接上干货! 大家,相信最近的这个事件,对于445端口已经是非常的小心了.勒索病毒 445端口是一个毁誉参半的端口,有了它我们可以在局域网中轻松访问各种共享文件夹或共享打印机,但也正是因为有了 ...

  9. js小知识colspan和rowspan

    colspan和rowspan这两个属性用于合并表格的列或者行. colspan是"column  span"(跨列)的缩写,所以colspan属性用在td标签中,用来跨列合并单元 ...

  10. C#小代码

    1.创建随机ID: Id = Guid.NewGuid().ToString("N"); 2.创建随机时间: CreationTime = DateTime.Now: int st ...