「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」
题目
设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。
示例:
输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]
提示:
0 <= len(arr) <= 100000
0 <= k <= min(100000, len(arr))
来源:力扣(LeetCode)leetcode-cn.com/problems/sm…
解题思路 - 排序
最简单的方式是使用 JavaScript 内置的排序方法按升序排序,排序后取前 k 个数,就是我们要的结果。
代码实现
var smallestK = function(arr, k) {
//将原数组拷贝一份
const ans = [...arr]
//通过数组 sort 方法进行排序,然后用 slice 方法截取前 k 个元素
return arr.sort((a, b) => a - b).slice(0, k)
};
解题思路 - 大顶堆
另一种方式是使用大顶堆,维护一个 k 个元素的大顶堆(小顶堆也可以,只是比较的方式不一样)。
循环遍历数组中的元素:
- 当大顶堆中的元素个数小于 k 时:将当前元素入队列;
- 当大顶堆中的元素个数等于 k 时:如果当前元素小于堆顶元素,则把堆顶元素出队列,把当前元素入队列;
- 循环结束后大顶堆中就是最小 k 个数;
相比排序,大顶堆的时间复杂度相对稳定,好的情况和坏的情况都是 O(nlogn)。
代码实现
var smallestK = function(arr, k) {
if (k === 0) return []
//初始化一个最大优先队列
const maxQueue = new MaxPriorityQueue()
arr.forEach(num => {
if (maxQueue.size() < k) {
//当队列里元素个数小于 k 个时,当前元素入队列
maxQueue.enqueue(num)
} else if (num < maxQueue.front()['priority']) {
//当队列里已经有了 k 个元素时
//并且当前元素小于队列中最大的元素时(大顶堆的堆顶)
//把最大元素出队列
maxQueue.dequeue()
//然后把当前元素入队列
maxQueue.enqueue(num)
}
})
//最后把最大优先队列转换成数组返回
return maxQueue.toArray().map(item => item.element)
};
如有错误欢迎指出,欢迎一起讨论!