LeetCode-面试题40. 最小的k个数

题目:

输入整数数组 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

解题思路:

(1) 遍历输入数组,将前k个数插入到推中;(利用PriorityQueue来做为堆的实现)
(2) 继续从输入数组中读入元素做为待插入整数,并将它与堆中最大值比较:
如果待插入的值比当前已有的最大值小,则用这个数替换当前已有的最大值;
如果待插入的值比当前已有的最大值还大,则抛弃这个数,继续读下一个数。
这样动态维护堆中这k个数,以保证它只储存输入数组中的前k个最小的数,最后输出ans即可
,时间复杂度O(nlogk) 

代码实现:

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {

       int[] ans = new int[k];
       int j = 0;
        if (arr == null || k <= 0 || k > arr.length) {
            return ans;
        }
        PriorityQueue<Integer> queue = new PriorityQueue<>(k, Collections.reverseOrder());
 
        for (int i = 0; i < arr.length; i++) {
 
            if (queue.size() < k) {
                queue.add(arr[i]);
            } else {
                if (arr[i] < queue.peek()) {
                    queue.remove();
                    queue.add(arr[i]);
                }
            }
        }
        while (!queue.isEmpty()) {
            ans[j++]=queue.remove();
        }
        return ans;
    }
}

复杂度分析

  • 时间复杂度:O(nlog k),其中 nn是数组 arr 的长度。由于大根堆实时维护前 k 小值,所以插入删除都是 O(nlog k) 的时间复杂度,最坏情况下数组里 n个数都会插入,所以一共需要 O(nlogk) 的时间复杂度。

  • 空间复杂度:O(k),因为大根堆里最多 k 个数。

发布了157 篇原创文章 · 获赞 1 · 访问量 2675

猜你喜欢

转载自blog.csdn.net/qq_34449717/article/details/105001161