leetcode lecture on algorithm interview in Dachang 12. Heap

Keywords: Algorithm

leetcode lecture on algorithm interview in Dachang 12. Heap

Video Explanation (efficient learning): Click to learn

catalog:

1. Introduction

2. Time and space complexity

3. Dynamic planning

4. Greed

5. Binary search

6. Depth first & breadth first

7. Double pointer

8. Sliding window

9. Bit operation

10. Recursion & divide and conquer

11 Pruning & backtracking

12. Reactor

13. Monotone stack

14. Sorting algorithm

15. Linked list

16.set&map

17. Stack

18. Queue

19. Array

20. String

21. Trees

22. Dictionary tree

23. Consolidation

24. Other types of questions

Extension:

Full binary tree: all nodes except leaf nodes have two child nodes. This kind of binary tree is called full binary tree, as shown in the following figure:

Complete binary tree: if the height of the binary tree is h, the number of nodes in other layers (1 ~ h-1) reaches the maximum except layer h, and layer h lacks several nodes continuously from right to left, which is a complete binary tree.

The heap is a complete binary tree, so we can implement it by array without wasting too much space. The value of each node in the heap is always not greater than or less than the value of its parent node. The heap is divided into large top heap and small top heap. The top of large top heap is the largest of the elements, and the top of small top heap is the smallest. When adding elements to the heap, we can dynamically adjust the order of elements in the heap The nature of the heap is always maintained.

Characteristics of reactor:
  • The internal data is orderly
  • Elements at the top of the heap can be ejected. The large top heap is the maximum value and the small top heap is the minimum value
  • After each new element is added or the top element is popped up, the heap is reorganized to require O(logn) time.
Implementation of heap
  • Implemented with an array, the heap corresponds to the elements in the array one by one from top to bottom and from left to right
  • Node parent node index parentIndex = [(index - 1) / 2], left node index leftIndex = index * 2 + 1, right node index rightIndex = index * 2 + 2
  • The first non leaf node is [size / 2]
Add elements to the heap
  • Add the new data to the last element of the tree, that is, the end of the array
  • Adjust the end node upward, that is, bubbleUp
  • Time complexity O(logn)

The animation is too large. Click to view it

Pop up elements in the heap
  • Exchange the values of the root node and the last node
  • Delete last node
  • Adjust the root node down
  • Time complexity O(logn)

The animation is too large. Click to view it

Complexity of getting the minimum value from an array:

Complete code
class Heap {
    constructor(comparator = (a, b) => a - b, data = []) {
        this.data = data;
        this.comparator = comparator;//comparator
        this.heapify();//Heap
    }

    heapify() {
        if (this.size() < 2) return;
        for (let i = Math.floor(this.size()/2)-1; i >= 0; i--) {
            this.bubbleDown(i);//bubbleDown operation
        }
    }

    peek() {
        if (this.size() === 0) return null;
        return this.data[0];//View the top of the heap
    }

    offer(value) {
        this.data.push(value);//Add array
        this.bubbleUp(this.size() - 1);//Adjust the position of the added elements in the small top heap
    }

    poll() {
        if (this.size() === 0) {
            return null;
        }
        const result = this.data[0];
        const last = this.data.pop();
        if (this.size() !== 0) {
            this.data[0] = last;//Swap the first and last elements
            this.bubbleDown(0);//bubbleDown operation
        }
        return result;
    }

    bubbleUp(index) {
        while (index > 0) {
            const parentIndex = (index - 1) >> 1;//Location of parent node
            //If the current element is smaller than the element of the parent node, the positions of the current node and the parent node are exchanged
            if (this.comparator(this.data[index], this.data[parentIndex]) < 0) {
                this.swap(index, parentIndex);//Swap the location of yourself and the parent node
                index = parentIndex;//Continuously take up the parent node for comparison
            } else {
                break;//If the current element is larger than the element of the parent node, it does not need to be processed
            }
        }
    }

    bubbleDown(index) {
        const lastIndex = this.size() - 1;//Location of the last node
        while (true) {
            const leftIndex = index * 2 + 1;//Location of left node
            const rightIndex = index * 2 + 2;//Location of the right node
            let findIndex = index;//Location of the bubbleDown node
            //Find the node with small value in the left and right nodes
            if (
                leftIndex <= lastIndex &&
                this.comparator(this.data[leftIndex], this.data[findIndex]) < 0
            ) {
                findIndex = leftIndex;
            }
            if (
                rightIndex <= lastIndex &&
                this.comparator(this.data[rightIndex], this.data[findIndex]) < 0
            ) {
                findIndex = rightIndex;
            }
            if (index !== findIndex) {
                this.swap(index, findIndex);//Swap the current element and the small value in the left and right nodes
                index = findIndex;
            } else {
                break;
            }
        }
    }

    swap(index1, index2) {//Swap the positions of the two elements in the heap
        [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]];
    }

    size() {
        return this.data.length;
    }
}

Posted by dynamicallystatic on Mon, 29 Nov 2021 20:57:55 -0800