js构建最小堆
class MinHeap {
constructor() {
this.heap = [];
}
// 获取父节点
getParentIndex(index){
return (index - 1) >> 1; // 获取商
}
// 获取左子节点
getLeftIndex(index){
return index * 2 + 1;
}
// 获取右子节点
getRightIndex(index){
return index * 2 + 2;
}
// 交换值
swap(index1, index2){
const tmp = this.heap[index1];
this.heap[index1] = this.heap[index2];
this.heap[index2] = tmp;
}
// 上移方法
shiftUp(index){
if(index === 0) return; // 堆顶,无需上移
// 拿到父亲节点
const parentIndex = this.getParentIndex(index);
// 根据条件交换
if(this.heap[parentIndex] > this.heap[index]){
this.swap(parentIndex, index);
this.shiftUp(parentIndex); // 继续上移
}
}
// 下移方法
shiftDown(index){
// 获取子节点
const leftIndex = this.getLeftIndex(index);
const rightIndex = this.getRightIndex(index);
// 比较左侧
if(this.heap[leftIndex] < this.heap[index]){
this.swap(leftIndex, index);
this.shiftDown(leftIndex);
}
// 比较右侧
if(this.heap[rightIndex] < this.heap[index]){
this.swap(rightIndex, index);
this.shiftDown(rightIndex);
}
}
// 插入方法
insert(value) {
this.heap.push(value); // 先放到最后一位
this.shiftUp(this.heap.length - 1); // 上移操作
}
// 删除堆顶
pop(){
this.heap[0] = this.heap.pop();
this.shiftDown(0);
}
// 获取堆顶
peek(){
return this.heap[0];
}
// 获取堆的大小
size(){
return this.heap.length;
}
}
LeetCode 215 数组中第k大元素
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
class MinHeap {
constructor() {
this.heap = [];
}
// 获取父节点
getParentIndex(index){
return (index - 1) >> 1; // 获取商
}
// 获取左子节点
getLeftIndex(index){
return index * 2 + 1;
}
// 获取右子节点
getRightIndex(index){
return index * 2 + 2;
}
// 交换值
swap(index1, index2){
const tmp = this.heap[index1];
this.heap[index1] = this.heap[index2];
this.heap[index2] = tmp;
}
// 上移方法
shiftUp(index){
if(index === 0) return; // 堆顶,无需上移
// 拿到父亲节点
const parentIndex = this.getParentIndex(index);
// 根据条件交换
if(this.heap[parentIndex] > this.heap[index]){
this.swap(parentIndex, index);
this.shiftUp(parentIndex); // 继续上移
}
}
// 下移方法
shiftDown(index){
// 获取子节点
const leftIndex = this.getLeftIndex(index);
const rightIndex = this.getRightIndex(index);
// 比较左侧
if(this.heap[leftIndex] < this.heap[index]){
this.swap(leftIndex, index);
this.shiftDown(leftIndex);
}
// 比较右侧
if(this.heap[rightIndex] < this.heap[index]){
this.swap(rightIndex, index);
this.shiftDown(rightIndex);
}
}
// 插入方法
insert(value) {
this.heap.push(value); // 先放到最后一位
this.shiftUp(this.heap.length - 1); // 上移操作
}
// 删除堆顶
pop(){
this.heap[0] = this.heap.pop();
this.shiftDown(0);
}
// 获取堆顶
peek(){
return this.heap[0];
}
// 获取堆的大小
size(){
return this.heap.length;
}
}
var findKthLargest = function(nums, k) {
const h = new MinHeap();
nums.forEach(n => {
h.insert(n);
if(h.size() > k){
h.pop();
}
});
return h.peek();
};
LeetCode 347 前 K 个高频元素
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function(nums, k) {
const map = new Map();
nums.forEach(n => {
map.set(n, map.has(n) ? map.get(n) + 1 : 1);
});
// console.log(map);
const list = Array.from(map).sort((a, b) => b[1] - a[1]);
// console.log(list);
return list.slice(0, k).map(n => n[0]);
};
用堆来做:
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
class MinHeap {
constructor() {
this.heap = [];
}
// 获取父节点
getParentIndex(index){
return (index - 1) >> 1; // 获取商
}
// 获取左子节点
getLeftIndex(index){
return index * 2 + 1;
}
// 获取右子节点
getRightIndex(index){
return index * 2 + 2;
}
// 交换值
swap(index1, index2){
const tmp = this.heap[index1];
this.heap[index1] = this.heap[index2];
this.heap[index2] = tmp;
}
// 上移方法
shiftUp(index){
if(index === 0) return; // 堆顶,无需上移
// 拿到父亲节点
const parentIndex = this.getParentIndex(index);
// 根据条件交换
if(this.heap[parentIndex] && this.heap[parentIndex].value > this.heap[index].value){
this.swap(parentIndex, index);
this.shiftUp(parentIndex); // 继续上移
}
}
// 下移方法
shiftDown(index){
// 获取子节点
const leftIndex = this.getLeftIndex(index);
const rightIndex = this.getRightIndex(index);
// 比较左侧
if(this.heap[leftIndex] && this.heap[leftIndex].value < this.heap[index].value){
this.swap(leftIndex, index);
this.shiftDown(leftIndex);
}
// 比较右侧
if(this.heap[rightIndex] && this.heap[rightIndex].value < this.heap[index].value){
this.swap(rightIndex, index);
this.shiftDown(rightIndex);
}
}
// 插入方法
insert(value) {
this.heap.push(value); // 先放到最后一位
this.shiftUp(this.heap.length - 1); // 上移操作
}
// 删除堆顶
pop(){
this.heap[0] = this.heap.pop();
this.shiftDown(0);
}
// 获取堆顶
peek(){
return this.heap[0];
}
// 获取堆的大小
size(){
return this.heap.length;
}
}
var topKFrequent = function(nums, k) {
const map = new Map();
nums.forEach(n => {
map.set(n, map.has(n) ? map.get(n) + 1 : 1);
});
const h = new MinHeap();
map.forEach((value, key) => {
h.insert({value, key});
if(h.size() > k){
h.pop();
}
});
return h.heap.map(a => a.key);
};
LeetCode 23 合并k个排序链表
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode[]} lists
* @return {ListNode}
*/
class MinHeap {
constructor() {
this.heap = [];
}
// 获取父节点
getParentIndex(index){
return (index - 1) >> 1; // 获取商
}
// 获取左子节点
getLeftIndex(index){
return index * 2 + 1;
}
// 获取右子节点
getRightIndex(index){
return index * 2 + 2;
}
// 交换值
swap(index1, index2){
const tmp = this.heap[index1];
this.heap[index1] = this.heap[index2];
this.heap[index2] = tmp;
}
// 上移方法
shiftUp(index){
if(index === 0) return; // 堆顶,无需上移
// 拿到父亲节点
const parentIndex = this.getParentIndex(index);
// 根据条件交换
if(this.heap[parentIndex] && this.heap[parentIndex].val > this.heap[index].val){
this.swap(parentIndex, index);
this.shiftUp(parentIndex); // 继续上移
}
}
// 下移方法
shiftDown(index){
// 获取子节点
const leftIndex = this.getLeftIndex(index);
const rightIndex = this.getRightIndex(index);
// 比较左侧
if(this.heap[leftIndex] && this.heap[leftIndex].val < this.heap[index].val){
this.swap(leftIndex, index);
this.shiftDown(leftIndex);
}
// 比较右侧
if(this.heap[rightIndex] && this.heap[rightIndex].val < this.heap[index].val){
this.swap(rightIndex, index);
this.shiftDown(rightIndex);
}
}
// 插入方法
insert(value) {
this.heap.push(value); // 先放到最后一位
this.shiftUp(this.heap.length - 1); // 上移操作
}
// 删除堆顶
pop(){
if(this.size() === 1) return this.heap.shift();
const top = this.heap[0];
this.heap[0] = this.heap.pop();
this.shiftDown(0);
return top;
}
// 获取堆顶
peek(){
return this.heap[0];
}
// 获取堆的大小
size(){
return this.heap.length;
}
}
var mergeKLists = function(lists) {
const res = new ListNode(0);
const h = new MinHeap(); //
let p = res;
lists.forEach(l => {
if(l) h.insert(l);
});
while(h.size()){
const n = h.pop(); // 弹出最小值
p.next = n;
p = p.next;
if(n.next) h.insert(n.next); // 插入
}
return res.next;
};