剑指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,后续更新)

猜你喜欢

转载自blog.csdn.net/autumn03/article/details/80289669
今日推荐