最小的k个数*****

题目描述

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

思路:

方法一:和上一个题目“数组中次数超过一半的数字”类似,平均时间复杂度是O(n),找出来的k个数字不一定是排序的,而且会修改输入的数组

方法二:O(nlogk)的算法,特别适合处理海量数据

 用最大堆保存这k个数,如果新的数字比堆顶小,新数入堆。

注意:java中的优先队列是基于堆实现的

抄一下别人的代码实现:

链接:https://www.nowcoder.com/questionTerminal/6a296eb82cf844ca8539b57c23e6e9bf
来源:牛客网

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) {
                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;
    }
}

答主的方法时间复杂度只有O(nlogk), 因为堆中总共k个数,每插入或删除一个数,都要调整一次堆,即时间复杂度为O(logk), 共循环n次,插入的次数最坏情况为n次,删除为n-k次,而平均下来插入次数也不少,所以大致估计时间复杂度就在nlogk



因为compareTo方法代表的是指定数如果大于参数的话那么则返回1,实现了comparator中重写compare方法,如果返回值是正数的话,那么就让第二个参数在前面,如果是负数的话,就让第一个数在前面。在这个方法中,如果o2大于o1那么返回1,就让o2在前面,就成为了最大堆

https://www.cnblogs.com/yongh/p/9945539.html

这个博客写的很清楚:

【Java】 用PriorityQueue实现最大最小堆

PriorityQueue(优先队列),一个基于优先级堆的无界优先级队列

实际上是一个堆(不指定Comparator时默认为最小堆),通过传入自定义的Comparator函数可以实现大顶堆。

PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
    @Override
    public int compare(Integer i1,Integer i2){
        return i2-i1;
    }
});

 案例: 剑指offer(41) 最小的k个数

PriorityQueue的常用方法有:poll(),offer(Object),size(),peek()等。

  •   插入方法(offer()、poll()、remove() 、add() 方法)时间复杂度为O(log(n)) ;
  •   remove(Object) 和 contains(Object) 时间复杂度为O(n);
  •   检索方法(peek、element 和 size)时间复杂度为常量。

PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
          使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器对元素进行排序。

猜你喜欢

转载自blog.csdn.net/qq_39474604/article/details/91360500