29 最小的K个数
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
考点不是排序啊。如果输入的数据大于内存你怎么排序?
最小堆和最小堆的时间复杂度都是n*logn,但是最小堆在k个数之后添加的话需要调整堆,但是最大堆只要每次和顶端的比较就可以啦。另外最小堆不能解决数字动态增加的情况。
最大堆思路(todo)
1.取数组前K个元素建最大堆。
2将数组剩余元素一次与最大堆堆顶元素比较,如果比堆顶元素小,则删除堆顶元素,该元素入堆。
我们先来复习一下堆排序:
 
1 import java.util.Arrays; 2 3 /** 4 * Created by chengxiao on 2016/12/17. 5 * 堆排序demo 6 */ 7 public class HeapSort { 8 public static void main(String []args){ 9 int []arr = {9,8,7,6,5,4,3,2,1}; 10 sort(arr); 11 System.out.println(Arrays.toString(arr)); 12 } 13 public static void sort(int []arr){ 14 //1.构建大顶堆 15 for(int i=arr.length/2-1;i>=0;i--){ 16 //从第一个非叶子结点从下至上,从右至左调整结构 17 adjustHeap(arr,i,arr.length); 18 } 19 //2.调整堆结构+交换堆顶元素与末尾元素 20 for(int j=arr.length-1;j>0;j--){ 21 swap(arr,0,j);//将堆顶元素与末尾元素进行交换 22 adjustHeap(arr,0,j);//重新对堆进行调整 23 } 24 25 } 26 27 /** 28 * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上) 29 * @param arr 30 * @param i 31 * @param length 32 */ 33 public static void adjustHeap(int []arr,int i,int length){ 34 int temp = arr[i];//先取出当前元素i 35 for(int k=i*2+1;k<length;k=k*2+1){//从i结点的左子结点开始,也就是2i+1处开始 36 if(k+1<length && arr[k]<arr[k+1]){//如果左子结点小于右子结点,k指向右子结点 37 k++; 38 } 39 if(arr[k] >temp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换) 40 arr[i] = arr[k]; 41 i = k; 42 }else{ 43 break; 44 } 45 } 46 arr[i] = temp;//将temp值放到最终的位置 47 } 48 49 /** 50 * 交换元素 51 * @param arr 52 * @param a 53 * @param b 54 */ 55 public static void swap(int []arr,int a ,int b){ 56 int temp=arr[a]; 57 arr[a] = arr[b]; 58 arr[b] = temp; 59 } 60 }
1 /* 2 *基于堆排序算法,构建最大堆。时间复杂度为O(nlogk) 3 *如果用快速排序,时间复杂度为O(nlogn); 4 *如果用冒泡排序,时间复杂度为O(n*k) 5 */ 6 import java.util.ArrayList; 7 public class Solution { 8 public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { 9 ArrayList<Integer> list=new ArrayList<Integer>(); 10 //检查输入的特殊情况 11 if(input==null || input.length<=0 || input.length<k){ 12 return list; 13 } 14 //构建最大堆 15 for(int len=k/2-1; len>=0; len--){ 16 adjustMaxHeapSort(input,len,k-1); 17 } 18 //从第k个元素开始分别与最大堆的最大值做比较,如果比最大值小,则替换并调整堆。 19 //最终堆里的就是最小的K个数。 20 int tmp; 21 for(int i=k; i<input.length; i++){ 22 if(input[i]<input[0]){ 23 tmp=input[0]; 24 input[0]=input[i]; 25 input[i]=tmp; 26 adjustMaxHeapSort(input,0,k-1); 27 } 28 } 29 for(int j=0; j<k; j++){ 30 list.add(input[j]); 31 } 32 return list; 33 } 34 35 public void adjustMaxHeapSort(int[] input, int pos, int length){ 36 int temp; 37 int child; 38 for(temp=input[pos]; 2*pos+1<=length; pos=child){ 39 child=2*pos+1; 40 if(child<length && input[child]<input[child+1]){ 41 child++; 42 } 43 if(input[child]>temp){ 44 input[pos]=input[child]; 45 }else{ 46 break; 47 } 48 } 49 input[pos]=temp; 50 } 51 }
以下方法是用PriorityQueue类去实现的,也比较简洁
1 import java.util.*; 2 //用最大堆保存这k个数,每次只和堆顶比,如果比堆顶小,删除堆顶,新数入堆。 3 public class Solution { 4 public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { 5 ArrayList<Integer> res = new ArrayList<>(); 6 if (input.length < k) 7 return res; 8 //(n, m) -> m - n是lambda表达式,传入一个比较器,规则是大的反而小,所以得到一个大顶堆,默认的是一个小顶堆 9 PriorityQueue<Integer> queue = new PriorityQueue<Integer>((n, m) -> m - n); 10 for (int num : input) { 11 queue.offer(num); 12 if (queue.size() > k) 13 queue.poll(); 14 } 15 while (!queue.isEmpty()) 16 res.add(queue.poll()); 17 return res; 18 } 19 }
下面这个方法也可以采取,用了collections.sort()方法
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 public class Solution { 5 public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { 6 List<Integer> list = new ArrayList<Integer>(); 7 ArrayList<Integer> res = new ArrayList<Integer>(); 8 if(input.length < k || input.length==0){ 9 return res; 10 } 11 for(int i=0;i<input.length;i++){ 12 list.add(input[i]); 13 } 14 Collections.sort(list); 15 for(int i = 0;i<k;i++){ 16 res.add(list.get(i)); 17 } 18 return res; 19 } 20 }
可以将整型输入数组直接从小到大排序
java.util.Arrays.sort(input);输入可以借鉴一下(出自https://blog.csdn.net/chainiao_zhang/article/details/77740213)
1 public class PopSortSolution { 2 public static void main(String[] args){ 3 Scanner scanner = new Scanner(System.in); 4 System.out.println("请输入一个数组,以空格隔开:"); 5 String str = scanner.nextLine(); 6 System.out.println("请输入K的值:"); 7 int k = scanner.nextInt(); 8 scanner.close(); //scanner使用后需要close,否则报警告。 9 String[] temp = str.split(" "); 10 int[] array = new int[temp.length]; 11 for(int i = 0; i<temp.length; i++){ 12 array[i] = Integer.parseInt(temp[i]); 13 } 14 Solution solution = new Solution(); 15 16 //GetLeastNumbet_Solution函数必须声明为static才能引用 17 System.out.println("最小" + k +"个数是:" +solution.GetLeastNumbers_Solution(array, k)); 18 }
            
 
作者:shareidea            
 
出处:https://www.cnblogs.com/shareidea94/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。   
 
                    
                
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号