zoukankan      html  css  js  c++  java
  • 求一个数组的最大k个数(java)

    问题描写叙述:求一个数组的最大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);
    	}
    
    }


  • 相关阅读:
    linux:centos7开启指定端口,开放外网访问
    zookeeper 集群搭建
    单机安装zookeeper的3.4.7版本
    CentOS7下安装jdk1.8并配置环境变量,防火墙设置开关
    Redis分布式锁的正确实现方式
    MySQl5.7 忘记密码怎么办?
    Flink 之Window(窗口)
    Flink之Sink(文件、Kafka、Redis、Es、Mysql)
    Canal同步Mysql数据至Hbase
    Flink 之分流Select与Split
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7141686.html
Copyright © 2011-2022 走看看