题目详情:
给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。
例如
输入:[4,5,1,6,2,7,3,8],4
返回值:[1,2,3,4]
说明:返回最小的4个数即可,返回[1,3,2,4]也可以
解题思路:
- 创建一个最大堆。
- 遍历整个数组,将数组中的元素依次插入最大堆中。
- 先将前k个元素先入队
- 在进行后面元素入队时,要先比较根节点值是否大于当前元素,如果根节点值>当前元素,就将根节点出队,当前元素入队
- 完成遍历后,堆中剩余的 k 个元素即为不去重的最小的 k 个数。
代码实现:
class MaxHeap {
constructor() {
this.heap = [];
}
getParentIndex(index) {
return Math.floor((index - 1) / 2);
}
getLeftChildIndex(index) {
return index * 2 + 1;
}
getRightChildIndex(index) {
return index * 2 + 2;
}
swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
shiftUp(index) {
if (index === 0) {
return;
}
const parentIndex = this.getParentIndex(index);
if (this.heap[parentIndex] < this.heap[index]) {
this.swap(this.heap, parentIndex, index);
this.shiftUp(parentIndex);
}
}
shiftDown(index) {
const leftChildIndex = this.getLeftChildIndex(index);
const rightChildIndex = this.getRightChildIndex(index);
let maxIndex = index;
if (
leftChildIndex < this.heap.length &&
this.heap[leftChildIndex] > this.heap[maxIndex]
) {
maxIndex = leftChildIndex;
}
if (
rightChildIndex < this.heap.length &&
this.heap[rightChildIndex] > this.heap[maxIndex]
) {
maxIndex = rightChildIndex;
}
if (maxIndex !== index) {
this.swap(this.heap, maxIndex, index);
this.shiftDown(maxIndex);
}
}
insert(value) {
this.heap.push(value);
this.shiftUp(this.heap.length - 1);
}
pop() {
if (this.heap.length === 0) {
return -1;
}
if (this.heap.length === 1) {
return this.heap.pop();
}
const top = this.heap[0];
this.heap[0] = this.heap.pop();
this.shiftDown(0);
return top;
}
peek() {
if (this.heap.length === 0) {
return -1;
}
return this.heap[0];
}
size() {
return this.heap.length;
}
}
function getLeastNumbers(numbers, k) {
const n = numbers.length;
if (k <= 0 || k > n) {
return [];
}
const heap = new MaxHeap();
for (let i = 0; i < n; i++) {
if (i < k) {
heap.insert(numbers[i]);
} else if (numbers[i] < heap.heap[0]) {
heap.pop();
heap.insert(numbers[i]);
}
}
const result = [];
for (let i = 0; i < k; i++) {
result.push(heap.pop());
}
return result;
}
// 测试示例
console.log(getLeastNumbers([4, 5, 1, 6, 2, 7, 3, 8], 4)); // 输出: [ 4, 3, 2, 1 ]