「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」
剑指 Offer 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]
「示例3:」
输入:arr = [3,2,1,7,56], k = 3
输出:[1,2,3] 或者 [3,2,1]
「示例4:」
输入:arr = [56,13,26,100,22,1], k = 1
输出:[1]
「示例5:」
输入:arr = [13,24,51,12,11,7,56,46], k = 2
输出:[11,12] 或者 [12,11]
「示例6:」
输入:arr = [1,6,4,8,12,45,17,5], k = 3
输出:[1,4,5,6]
「提示: 」
0 <= k <= arr.length <= 100000 <= arr[i] <= 10000
解题思路
1. 由题意可知,这是一道求最值的题目,对于求最值的题目我们都可以使用堆来进行解题
2. 我们可以构建一个大顶堆
3. 通过循环测试用例给我们的数组,判断当前值是否小于于堆顶的元素或者堆里面的元素小于k的时候,就向堆里面添加该值
4. 最后返回堆内的元素即可
代码实现
/**
* 剑指 Offer 40. 最小的k个数
* @param {number[]} arr
* @param {number} k
* @return {number[]}
*/
class BigHeap {
constructor(k) {
this.arr = [];
this.size = 0;
this.max = k;
}
push(val) {
this.arr.push(val);
this.size++;
if (this.size > 1) {
let cur = this.size - 1,
parent = (cur - 1) >> 1;
while (cur > 0 && this.arr[cur] > this.arr[parent]) {
[this.arr[cur], this.arr[parent]] = [this.arr[parent], this.arr[cur]];
cur = parent;
parent = (cur - 1) >> 1;
}
}
if (this.size > this.max) this.pop();
}
pop() {
this.arr[0] = this.arr.pop();
this.size--;
let cur = 0,
childl = 1,
childr = 2;
while (
(childl < this.size && this.arr[childl] > this.arr[cur]) ||
(childr < this.size && this.arr[childr] > this.arr[cur])
) {
if (childl < this.size && this.arr[childl] < this.arr[childr]) {
[this.arr[childr], this.arr[cur]] = [this.arr[cur], this.arr[childr]];
cur = childr;
} else {
[this.arr[childl], this.arr[cur]] = [this.arr[cur], this.arr[childl]];
cur = childl;
}
childr = cur * 2 + 2;
childl = cur * 2 + 1;
}
}
top() {
return this.arr[0];
}
}
var getLeastNumbers = function (arr, k) {
if (k === 0) return [];
const heap = new BigHeap(k);
for (let i = 0; i < arr.length; i++) {
if (heap.size < k || arr[i] < heap.top()) heap.push(arr[i]);
}
return heap.arr;
};
如果你对这道题目还有疑问的话,可以在评论区进行留言;