[JavaScript version of data structure and algorithm for interviews with large companies] Chapter 10 "Heap" of data structure

Chapter 10 Data Structure "Heap"

10.1 Introduction to Heaps

insert image description here
insert image description here
insert image description here
insert image description here

The Kth smallest element
Construct a maximum heap, the steps are the same as above

10.2 JavaScript Implementation: The Min-Heap Class

insert image description here

Create a new empty heap class

class MinHeap{//Create a new class to store the heap array
constructor() { this.heap = [];//Create a new array named heap and bind it to this }

}

insert image description here
Insert element code:

class MinHeap {
    
    //1、新建一个类来存放堆数组
    constructor() {
    
    //2
        this.heap = [];//3、新建一个名为heap的数组,把它绑定到this上
    }
    swap(i1, i2) {
    
    //12、实现交换方法
        var temp = this.heap[i1];//声明一个临时变量来存i1的值
        this.heap[i1] = this.heap[i2];
        this.heap[i2] = temp;

    }
    getParentIndex(i) {
    
    //8、拿到这个值的父节点 
        return (i - 1) >> 1;//9、法一:二进制方法
        // return Math.floor((i - 1) / 2); 法二
    }
    shiftUp(index) {
    
    //7、实现shiftUp()方法
        //不停的和父节点交换,直到父节点小于它的子节点
        if (index == 0) {
    
     return; }//14、如果上移的值等于堆顶,那就不用上移了
        var parentIndex = this.getParentIndex(index);
        if (this.heap[parentIndex] > this.heap[index]) {
    
    //10、如果当前节点大于父节点,那么就需要交换
            this.swap(parentIndex, index);//11、交换下标
            this.shiftUp(parentIndex);//13、继续上移操作
        }
    }
    insert(value) {
    
    //4、插入方法:插入一个值
        this.heap.push(value);//5、把这个值推入heap数组的最后一位
        this.shiftUp(this.heap.length - 1);//6、封装一个shifUp(要上移的值的数组下标)方法,让值上移,
    }

}

var h = new MinHeap();//15、声明一个变量h它等于实例化的最小堆
h.insert(3);//16、插入值3
h.insert(2);
h.insert(1);

insert image description here
Remove heap top code:

class MinHeap {
    
    //1、新建一个类来存放堆数组
    constructor() {
    
    //2
        this.heap = [];//3、新建一个名为heap的数组,把它绑定到this上
    }
    swap(i1, i2) {
    
    //12、实现交换方法
        var temp = this.heap[i1];//声明一个临时变量来存i1的值
        this.heap[i1] = this.heap[i2];
        this.heap[i2] = temp;

    }
    getParentIndex(i) {
    
    //8、拿到这个值的父节点 
        return (i - 1) >> 1;//9、法一:二进制方法
        // return Math.floor((i - 1) / 2); 法二
    }
    getLeftIndex(i) {
    
    //拿到当前节点的左节点 
        return i * 2 + 1;
    }
    getRightIndex(i) {
    
    //拿到当前节点的右节点 
        return i * 2 + 2;
    }

    shiftUp(index) {
    
    //7、实现shiftUp()方法
        //不停的和父节点交换,直到父节点小于它的子节点
        if (index == 0) {
    
     return; }//14、如果上移的值等于堆顶,那就不用上移了
        var parentIndex = this.getParentIndex(index);
        if (this.heap[parentIndex] > this.heap[index]) {
    
    //10、如果当前节点大于父节点,那么就需要交换
            this.swap(parentIndex, index);//11、交换下标
            this.shiftUp(parentIndex);//13、继续上移操作
        }
    }
    shiftDown(index) {
    
    //实现下移算法
        var leftIndex = this.getLeftIndex(index);
        var 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) {
    
    //4、插入方法:插入一个值
        this.heap.push(value);//5、把这个值推入heap数组的最后一位
        this.shiftUp(this.heap.length - 1);//6、封装一个shifUp(要上移的值的数组下标)方法,让值上移,
    }
    pop() {
    
    //下移方法操作 
        this.heap[0] = this.heap.pop();//把数组的最后一位转移到数组的头部
        this.shiftDown(0);//this.shiftDown(“要下元素的数组下标“)把头部元素进行下移操作
    }

}

var h = new MinHeap();//15、声明一个变量h它等于实例化的最小堆
h.insert(3);//16、插入值3
h.insert(2);
h.insert(1);
h.pop();//调用移除方法

insert image description here

class MinHeap {
    
    //1、新建一个类来存放堆数组
    constructor() {
    
    //2
        this.heap = [];//3、新建一个名为heap的数组,把它绑定到this上
    }
    swap(i1, i2) {
    
    //12、实现交换方法
        var temp = this.heap[i1];//声明一个临时变量来存i1的值
        this.heap[i1] = this.heap[i2];
        this.heap[i2] = temp;

    }
    getParentIndex(i) {
    
    //8、拿到这个值的父节点 
        return (i - 1) >> 1;//9、法一:二进制方法
        // return Math.floor((i - 1) / 2); 法二
    }
    getLeftIndex(i) {
    
    //拿到当前节点的左节点 
        return i * 2 + 1;
    }
    getRightIndex(i) {
    
    //拿到当前节点的右节点 
        return i * 2 + 2;
    }

    shiftUp(index) {
    
    //7、实现shiftUp()方法
        //不停的和父节点交换,直到父节点小于它的子节点
        if (index == 0) {
    
     return; }//14、如果上移的值等于堆顶,那就不用上移了
        var parentIndex = this.getParentIndex(index);
        if (this.heap[parentIndex] > this.heap[index]) {
    
    //10、如果当前节点大于父节点,那么就需要交换
            this.swap(parentIndex, index);//11、交换下标
            this.shiftUp(parentIndex);//13、继续上移操作
        }
    }
    shiftDown(index) {
    
    //实现下移算法
        var leftIndex = this.getLeftIndex(index);
        var 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) {
    
    //4、插入方法:插入一个值
        this.heap.push(value);//5、把这个值推入heap数组的最后一位
        this.shiftUp(this.heap.length - 1);//6、封装一个shifUp(要上移的值的数组下标)方法,让值上移,
    }
    pop() {
    
    //下移方法操作 
        this.heap[0] = this.heap.pop();//把数组的最后一位转移到数组的头部
        this.shiftDown(0);//this.shiftDown(“要下元素的数组下标“)把头部元素进行下移操作
    }
    peek(){
    
    //获取堆顶
        return this.heap[0];
    }
    size(){
    
    //获取堆的大小
        return this.heap.length;
    }

}

10.3 LeetCode: 3215. The Kth Largest Element in an Array

insert image description here
insert image description here
insert image description here
Code:

class MinHeap {
    
    //1、新建一个类来存放堆数组
    constructor() {
    
    //2
        this.heap = [];//3、新建一个名为heap的数组,把它绑定到this上
    }
    swap(i1, i2) {
    
    //12、实现交换方法
        var temp = this.heap[i1];//声明一个临时变量来存i1的值
        this.heap[i1] = this.heap[i2];
        this.heap[i2] = temp;

    }
    getParentIndex(i) {
    
    //8、拿到这个值的父节点 
        return (i - 1) >> 1;//9、法一:二进制方法
        // return Math.floor((i - 1) / 2); 法二
    }
    getLeftIndex(i) {
    
    //拿到当前节点的左节点 
        return i * 2 + 1;
    }
    getRightIndex(i) {
    
    //拿到当前节点的右节点 
        return i * 2 + 2;
    }

    shiftUp(index) {
    
    //7、实现shiftUp()方法
        //不停的和父节点交换,直到父节点小于它的子节点
        if (index == 0) {
    
     return; }//14、如果上移的值等于堆顶,那就不用上移了
        var parentIndex = this.getParentIndex(index);
        if (this.heap[parentIndex] > this.heap[index]) {
    
    //10、如果当前节点大于父节点,那么就需要交换
            this.swap(parentIndex, index);//11、交换下标
            this.shiftUp(parentIndex);//13、继续上移操作
        }
    }
    shiftDown(index) {
    
    //实现下移算法
        var leftIndex = this.getLeftIndex(index);
        var 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) {
    
    //4、插入方法:插入一个值
        this.heap.push(value);//5、把这个值推入heap数组的最后一位
        this.shiftUp(this.heap.length - 1);//6、封装一个shifUp(要上移的值的数组下标)方法,让值上移,
    }
    pop() {
    
    //下移方法操作 
        this.heap[0] = this.heap.pop();//把数组的最后一位转移到数组的头部
        this.shiftDown(0);//this.shiftDown(“要下元素的数组下标“)把头部元素进行下移操作
    }
    peek(){
    
    
        return this.heap[0];
    }
    size(){
    
    
        return this.heap.length;
    }

}

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findKthLargest = function(nums, k) {
    
    
    var h =new MinHeap();
    nums.forEach(n=>{
    
    //
        h.insert(n);
        if(h.size()> k){
    
    
            h.pop();
        }
    });
    return h.peek();
};

10.4 LeetCode: 347. Top K high-frequency elements

insert image description here
Code:

class MinHeap {
    
    //1、新建一个类来存放堆数组
    constructor() {
    
    //2
        this.heap = [];//3、新建一个名为heap的数组,把它绑定到this上
    }
    swap(i1, i2) {
    
    //12、实现交换方法
        var temp = this.heap[i1];//声明一个临时变量来存i1的值
        this.heap[i1] = this.heap[i2];
        this.heap[i2] = temp;

    }
    getParentIndex(i) {
    
    //8、拿到这个值的父节点 
        return (i - 1) >> 1;//9、法一:二进制方法
        // return Math.floor((i - 1) / 2); 法二
    }
    getLeftIndex(i) {
    
    //拿到当前节点的左节点 
        return i * 2 + 1;
    }
    getRightIndex(i) {
    
    //拿到当前节点的右节点 
        return i * 2 + 2;
    }

    shiftUp(index) {
    
    //7、实现shiftUp()方法
        //不停的和父节点交换,直到父节点小于它的子节点
        if (index == 0) {
    
     return; }//14、如果上移的值等于堆顶,那就不用上移了
        var parentIndex = this.getParentIndex(index);
        if (this.heap[parentIndex]&& this.heap[parentIndex].value > this.heap[index].value) {
    
    
            this.swap(parentIndex, index);//11、交换下标
            this.shiftUp(parentIndex);//13、继续上移操作
        }
    }
    shiftDown(index) {
    
    //实现下移算法
        var leftIndex = this.getLeftIndex(index);
        var 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) {
    
    //4、插入方法:插入一个值
        this.heap.push(value);//5、把这个值推入heap数组的最后一位
        this.shiftUp(this.heap.length - 1);//6、封装一个shifUp(要上移的值的数组下标)方法,让值上移,
    }
    pop() {
    
    //下移方法操作 
        this.heap[0] = this.heap.pop();//把数组的最后一位转移到数组的头部
        this.shiftDown(0);//this.shiftDown(“要下元素的数组下标“)把头部元素进行下移操作
    }
    peek(){
    
    
        return this.heap[0];
    }
    size(){
    
    
        return this.heap.length;
    }

}

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
    
    
    var map = new Map();
    nums.forEach(n=>{
    
    
        map.set(n,map.has(n)?map.get(n)+1:1);
    });
    var h= new MinHeap();
    map.forEach((value,key)=>{
    
    
        h.insert({
    
    value,key});
        if(h.size()>k){
    
    
            h.pop();
        }
    });
    return h.heap.map(a=>a.key);
    };

10.5 LeetCode: 23. Merge K sorted lists

insert image description here
insert image description here
insert image description here
insert image description here
Code:

class MinHeap {
    
    //1、新建一个类来存放堆数组
    constructor() {
    
    //2
        this.heap = [];//3、新建一个名为heap的数组,把它绑定到this上
    }
    swap(i1, i2) {
    
    //12、实现交换方法
        var temp = this.heap[i1];//声明一个临时变量来存i1的值
        this.heap[i1] = this.heap[i2];
        this.heap[i2] = temp;

    }
    getParentIndex(i) {
    
    //8、拿到这个值的父节点 
        return (i - 1) >> 1;//9、法一:二进制方法
        // return Math.floor((i - 1) / 2); 法二
    }
    getLeftIndex(i) {
    
    //拿到当前节点的左节点 
        return i * 2 + 1;
    }
    getRightIndex(i) {
    
    //拿到当前节点的右节点 
        return i * 2 + 2;
    }

    shiftUp(index) {
    
    //7、实现shiftUp()方法
        //不停的和父节点交换,直到父节点小于它的子节点
        if (index == 0) {
    
     return; }//14、如果上移的值等于堆顶,那就不用上移了
        var parentIndex = this.getParentIndex(index);
        if (this.heap[parentIndex] && this.heap[parentIndex].val > this.heap[index].val) {
    
    
            this.swap(parentIndex, index);//11、交换下标
            this.shiftUp(parentIndex);//13、继续上移操作
        }
    }
    shiftDown(index) {
    
    //实现下移算法
        var leftIndex = this.getLeftIndex(index);
        var 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) {
    
    //4、插入方法:插入一个值
        this.heap.push(value);//5、把这个值推入heap数组的最后一位
        this.shiftUp(this.heap.length - 1);//6、封装一个shifUp(要上移的值的数组下标)方法,让值上移,
    }
    pop() {
    
    //下移方法操作 
        this.heap[0] = this.heap.pop();//把数组的最后一位转移到数组的头部
        this.shiftDown(0);//this.shiftDown(“要下元素的数组下标“)把头部元素进行下移操作
    }
    peek(){
    
    
        if(this.size() === 1) return this.heap.shift();
        return this.heap[0];
        this.heap[0]=this.heap.pop();
        this.shiftDown(0);
        return top;
    }
    size(){
    
    
        return this.heap.length;
    }

}

/**
 * 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}
 */
var mergeKLists = function(lists) {
    
    
    var res = new ListNode(0);
    let p = res;
    var h = new MinHeap();
    lists.forEach(l => {
    
    
        if(l) h.insert(l);
    });
    while (h.size()){
    
    
        var n = h.pop();
        p.next = n;
        p = p.next;
        if(n.next) h.insert(n.next);
    }
    return res.next;

};

10.6 Heap Summary

insert image description here

insert image description here

Guess you like

Origin blog.csdn.net/qiqizgl777/article/details/129161319