package com.leetcode.leetcode.licm;

import java.util.PriorityQueue;
import java.util.Queue;

/**
* @description:
*
* 输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
*
*  
*
* 示例 1:
*
* 输入:arr = [3,2,1], k = 2
* 输出:[1,2] 或者 [2,1]
* 示例 2:
*
* 输入:arr = [0,1,2,1], k = 1
* 输出:[0]
*  
*
* 限制:
*
* 0 <= k <= arr.length <= 10000
* 0 <= arr[i] <= 10000
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*
* @author: licm
* @create: 2021-08-11 09:59
<strong>/
public class Lc_剑指Offer40最小的k个数 {
/</strong>
* 大根堆(前 K 小) / 小根堆(前 K 大),Java中有现成的 PriorityQueue,实现起来最简单:O(NlogK)O(NlogK)
* 本题是求前 K 小,因此用一个容量为 K 的大根堆,每次 poll 出最大的数,那堆中保留的就是前 K 小啦(注意不是小根堆!小根堆的话需要把全部的元素都入堆,那是 O(NlogN)O(NlogN)😂,就不是 O(NlogK)O(NlogK)啦~~)
* 这个方法比快排慢,但是因为 Java 中提供了现成的 PriorityQueue(默认小根堆),所以实现起来最简单,没几行代码~
*
* 作者:sweetiee
* 链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/3chong-jie-fa-miao-sha-topkkuai-pai-dui-er-cha-sou/
* 来源:力扣(LeetCode)
* 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
* @param arr
* @param k
* @return
*/
public static int[] getLeastNumbers(int[] arr, int k) {
if(k==0 || arr.length==0){
return new int[0];
}
//默认小根堆,大根堆重写比较器
Queue<Integer> pq = new PriorityQueue<>((v1,v2)-> v2-v1);
for(int num:arr){
if(pq.size()<k){
pq.offer(num);
}else if(num<pq.peek()){
pq.poll();
pq.offer(num);
}
}
//返回队中元素
int[] res = new int[pq.size()];
int idx = 0;
for(int num:pq){
res[idx++] = num;
}
return res;
}

public static void main(String[] args) {
int[] nums = {1,2,3,4,5};
int k =2;
int[] leastNumbers = getLeastNumbers(nums, k);
for (int le:leastNumbers){
System.out.println(le);
}
}
}