题目:
输入整数数组 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 个数。