40、最小的k个数

穿精又带淫゛_ 提交于 2020-01-08 09:45:47

1、题目描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

2、思路:这道题有三种解法,分别是排序,分治,最大堆(优先队列)

解法一:排序解法,先对输入的数组排序,排序的最快的时间复杂度为o(nlogn),然后取排序后的前k个数。总的时间复杂度为o(nlogn)。

解法二:分治方法,模仿快速排序思想,每次都取数组的第k个数,然后将比第k个数小的数放在数组的左边,比第k个数大的数放在数组的右边。然后不断的调整下去。时间复杂度为O(n)。

  这个方法不适合于大数据量,因为需要改变数组的结构,并且要把数组全部加载到内存当中,若内存不够大,就不可以。

解法三:最大堆(优先队列)。首先创建一个容量为k的优先队列,传入比较器,重写其 compare 方法,以保证每次从队列中弹出的元素是最大值。这样优先队列中的元素个数小于k的时候,只需要将数组中取出来的数字直接插入到队列中即可;当优先队列的元素已满,只需要比较堆顶元素和待插入元素,若堆订元素小于待插入元素,那就舍弃,若待插入元素比堆订元素小,那就移除堆订元素,将数组元素插入其中。

  这个方法的好处就是不改变数组的结构,内存占用小,适合于海量数据的处理,从最大堆中获取k个数字的最大值的时间复杂度为o(1),而删除和插入元素的操作的时间复杂度为o(logk)。因此这种方法的总的时间复杂度为o(nlogk)。比解法二差一点但适合于海量数据的存储。

 

3、代码:直接拷的,后期需自己实现

import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
   public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
       ArrayList<Integer> result = new ArrayList<Integer>();
       int length = input.length;
       if(k > length || k == 0){
           return result;
       }
        PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
 
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });
        for (int i = 0; i < length; i++) {
            if (maxHeap.size() != k) {          //最大堆中的元素没有k个,直接插入
                maxHeap.offer(input[i]);
            } else if (maxHeap.peek() > input[i]) {          //最大堆满了就比较堆顶元素和待插入元素          //待插入元素小,那就把堆顶的最大元素删掉,将该元素插入堆                Integer temp = maxHeap.poll();
                temp = null;
                maxHeap.offer(input[i]);
            }
        }
        for (Integer integer : maxHeap) {
            result.add(integer);
        }
        return result;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!