堆
- 堆是一种特殊的完全二叉树;
- js 中通常用数组表示堆;
特点
- 所以的节点都大于等于(最大堆)或小于等于(最小堆)它的子节点;
- 左侧节点的位置是 2*index + 1;
- 右侧节点的位置是 2*index + 2;
- 父节点位置是(index - 1)/2;
示例
我们以数组[1,3,6,5,8,9]为例,看一下最大堆是怎么生成的。
应用
- 堆能高效、快速的找出最大值和最小值,事件复杂度 O(1);
- 找出第 k 个最大(小)的元素;
最小堆的实现
class MinHeap {
constructor(maxSize) {
this.heap = [];
this.maxSize = maxSize;
}
insert(val) {
this.heap.push(val);
this.siftUp(this.heap.length - 1);
if (this.size() > this.maxSize) {
this.pop();
}
}
getParentIndex(index) {
return (index - 1) >> 1; // 二进制右移一位
}
getLeftIndex(index) {
return index * 2 + 1;
}
getRightIndex(index) {
return index * 2 + 2;
}
siftUp(index) {
if (index === 0) return;
let parentIndex = this.getParentIndex(index);
if (this.heap[index] < this.heap[parentIndex]) {
this.swap(index, parentIndex);
this.siftUp(parentIndex);
}
}
pop() {
this.heap[0] = this.heap.pop();
this.siftDown(0);
}
swap(index1, index2) {
[this.heap[index1], this.heap[index2]] = [
this.heap[index2],
this.heap[index1],
];
}
siftDown(index) {
let leftIndex = this.getLeftIndex(index);
let rightIndex = this.getRightIndex(index);
if (this.heap[leftIndex] < this.heap[index]) {
this.swap(leftIndex, index);
this.siftDown(leftIndex);
}
if (this.heap[rightIndex] < this.heap[index]) {
this.swap(rightIndex, index);
this.siftDown(rightIndex);
}
}
// 获取堆顶元素
peak() {
return this.heap[0];
}
size() {
return this.heap.length;
}
}
力扣刷题
题目:数据流中的第 K 大元素
解析:
- 创建一个最小堆,用来保存前 k 个元素
- 每次添加一个元素,如果大于堆顶元素,则替换堆顶元素,并且重新调整堆
代码
class MinHeap {
constructor(maxSize) {
this.heap = [];
this.maxSize = maxSize;
}
insert(val) {
this.heap.push(val);
this.siftUp(this.heap.length - 1);
if (this.size() > this.maxSize) {
this.pop();
}
}
getParentIndex(index) {
return (index - 1) >> 1; // 二进制右移一位
}
getLeftIndex(index) {
return index * 2 + 1;
}
getRightIndex(index) {
return index * 2 + 2;
}
siftUp(index) {
if (index === 0) return;
let parentIndex = this.getParentIndex(index);
if (this.heap[index] < this.heap[parentIndex]) {
this.swap(index, parentIndex);
this.siftUp(parentIndex);
}
}
pop() {
this.heap[0] = this.heap.pop();
this.siftDown(0);
}
swap(index1, index2) {
[this.heap[index1], this.heap[index2]] = [
this.heap[index2],
this.heap[index1],
];
}
siftDown(index) {
let leftIndex = this.getLeftIndex(index);
let rightIndex = this.getRightIndex(index);
if (this.heap[leftIndex] < this.heap[index]) {
this.swap(leftIndex, index);
this.siftDown(leftIndex);
}
if (this.heap[rightIndex] < this.heap[index]) {
this.swap(rightIndex, index);
this.siftDown(rightIndex);
}
}
// 获取堆顶元素
peak() {
return this.heap[0];
}
size() {
return this.heap.length;
}
}
/**
* @param {number} k
* @param {number[]} nums
*/
var KthLargest = function (k, nums) {
this.minHead = new MinHeap(k);
nums.forEach((m) => {
this.minHead.insert(m);
});
};
/**
* @param {number} val
* @return {number}
*/
KthLargest.prototype.add = function (val) {
this.minHead.insert(val);
return this.minHead.peak();
};
写在最后
- 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎
点赞和关注