剑指offer--30.最小的k个数

题目:输入n个整数,找出其中最小的k个数,eg,输入input={4,5,1,6,2,7,3,8},则最小的四个数是1,2,3,4

思路:把输入的n个整数排序,排序之后位于最前面的k个数就是最小的k个数,算法时间复杂度为O(nlogn)

       public static ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
		ArrayList<Integer> list=new ArrayList<>();
		if(input==null || k<=0 || k>input.length){
			return list;
		}
		Arrays.sort(input);
		for(int i=0;i<k;i++){
			list.add(input[i]);
		}
		return list;
	}

剑指offer解法一:基于Partition函数,基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的所有数字都位于数组的右边,这样调整之后,位于数组中左边的k个数字就是最小的k个数字,但是这k个数字不一定是排序的

import java.util.*;
public class wr30MinKNumber {
	
	public static ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
		ArrayList<Integer> list=new ArrayList<>();
		if(input==null || k<=0 || k>input.length){
			return list;
		}
		Arrays.sort(input);
		for(int i=0;i<k;i++){
			list.add(input[i]);
		}
		return list;
	}
	
	public static ArrayList<Integer> getLeastNumbers(int []input,int k){
		ArrayList<Integer> list=new ArrayList<>();
		if(input==null || k>input.length || k<=0){
			return list;
		}
		int low=0;
		int high=input.length-1;
		int index=Partition(input,k,low,high);
		while(index!=k-1){
			if(index>k-1){
				index=Partition(input,k,low,index-1);
			}else{
				index=Partition(input,k,index+1,high);
			}
		}
		for(int i=0;i<k;i++){
			list.add(input[i]);
		}
		return list;
	}
	
	public static int Partition(int []input,int k,int low,int high){
		int key=input[k-1];
		swap(input,k-1,low);
		while(low<high){
			while(low<high && input[high]>=key){
				high--;
			}
			swap(input,low,high);
			while(low<high && input[low]<key){
				low++;
			}
			swap(input,low,high);
		}
		return low;
	}
	
	public static void swap(int [] input, int low,int high){
		int temp=input[high];
		input[high]=input[low];
		input[low]=temp;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int []input={4,5,1,6,2,7,3,8};
//		ArrayList<Integer> list=GetLeastNumbers_Solution(input,4);
		ArrayList<Integer> list=getLeastNumbers(input,4);
		for(int i:list){
			System.out.print(i+" ");
		}		
	}
}

剑指offer解法二:O(nlogk)算法,适合处理海量数据。我们可以先创建一个大小为k的数据容器存储最小的k个数字,接着每次从输入的n个整数中读入一个数,如果容器中已有的数字少于k个,就直接把该数放入容器中;如果容器中已有k个数字,即容器已满,找出已有k个数中的最大值,然后拿这次待插入的整数和最大值比较,如果待插入的值比当前已有的最大值小,则用这个数替换已有的最大值。由于每次都需要找到k个整数中的最大数字,可以用最大堆来完成,在最大堆中,根结点的值总是大于它的子树中任意结点的值,于是每次可以在O(1)得到已有的k个数字最大值,O(lonk)完成删除和插入操作。(代码正在理解ing,后续更新)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值