题目:输入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,后续更新)