[Maximum and minimum heap algorithm] Find the Kth largest element in the array / find the median of the data

STL priority queue for C++

The way to construct the maximum and minimum heap

priority_queue<int> big_heap; // 默认构造最大堆
priority_queue<int, vector<int>, greater<int>> small_heap; // 构造最小堆
priority_queue<int, vector<int>, less<int>> big_heap2; // 构造最大堆

Priority queue and its function examples

#include <iostream>
#include <stack>
#include <queue>
using namespace std;

// 以下为测试
int main() {
    
    
    
    priority_queue<int> big_heap; // 默认构造最大堆
    priority_queue<int, vector<int>, greater<int>> small_heap; // 构造最小堆
    priority_queue<int, vector<int>, less<int>> big_heap2; // 构造最大堆
    if (big_heap.empty()) {
    
    
        cout << "最大堆为空!" << endl;
    }
    int test[] = {
    
     6,10,1,7,99,4,33 };
    for (int i = 0; i < 7; i++) {
    
    
        big_heap.push(test[i]);
    }
    cout << "最大堆堆顶,即最大值为 " << big_heap.top() << endl;
    big_heap.push(1000);
    cout << "最大堆堆顶,即最大值为 " << big_heap.top() << endl;
    for (int i = 0; i < 3; i++)
    {
    
    
        big_heap.pop();
    }
    cout << "最大堆堆顶,即最大值为 " << big_heap.top() << endl;
    cout << "最大堆的元素个数为:" << big_heap.size() << endl;
    return 0;
}

result:

最大堆为空!
最大堆堆顶,即最大值为 99
最大堆堆顶,即最大值为 1000
最大堆堆顶,即最大值为 10
最大堆的元素个数为:5

Find the Kth largest element in the array

  1. Problem: Find the k-th largest element in an unsorted array. Please note that what you need to find is the k-th largest element after sorting the array, not the k-th different element.
  2. Solution: Maintain a minimum team with a size of K. When the number of elements in the heap is less than K, the new element enters the heap directly; otherwise, when the top element of the heap is smaller than the new element, the top of the heap is popped, and the new element is added to the heap.
  3. For example: [3,2,1,5,6,4] and k = 2. Since k=2, the first 3 and 2 enter the smallest heap directly, the top of the heap is 2, which is greater than 1, so no operation is required, and then 2 is greater than 5. If 5 enters the heap, but 2 is popped out, and so on, the smallest heap of two elements is formed. The top of the heap is 5, which is the Kth largest number you want. The reason is: the smallest of the two (k) numbers is the second largest among the six numbers. Taste, you fine taste!
class Solution {
    
    
public:
    int findKthLargest(vector<int>& nums, int k) {
    
    
        priority_queue<int, vector<int>, greater<int>> Q;
        for (int i = 0; i < nums.size(); i++)
        {
    
    
            if (Q.size() < k)
                Q.push(nums[i]);
            else if (Q.top() < nums[i]) {
    
    
                Q.pop();
                Q.push(nums[i]);
            }
        }
        return Q.top();
    }
};

Find the median of a set of data

problem

Find the median of a set of data, the median is the number in the middle of the ordered list. If the length of the list is even, the median is the average of the middle two numbers.
For example, the
median of [2,3,4] is 3 The median of
[2,3] is (2 + 3) / 2 = 2.5
Design a data structure that supports the following two operations:

  • void addNum(int num)-Add an integer from the data stream to the data structure.
  • double findMedian()-Returns the median of all current elements.

solve

  1. Idea: Dynamically maintain a maximum heap and a minimum heap, each of which stores half of the data, provided that the top of the largest heap is smaller than the top of the smallest heap (or equal, which means that the data is divided into two according to the size Half. If the number of elements in the entire data set is odd, there will be one more element in one heap than the other, that is, the top of the multi-element heap is the median; if the number of elements is even, Then take the average of the top elements of the two piles as the median.
    Insert picture description here

  2. The algorithm mainly maintains the maximum heap and the minimum heap when adding new data. There are three situations:

    • Case 1, the current maximum heap and minimum heap elements are the same, then check: if the new element is less than the top of the maximum heap, add it to the largest heap; if the new element is greater than the top of the minimum heap, add it to the smallest heap.
    • Case 2: The largest heap is one element more than the smallest heap, then check: if the new element is larger than the largest heap element, just add it to the smallest heap; otherwise, if the new element is smaller or equal to the largest heap element, be careful. At this time, you can’t directly add to the largest heap (it will cause the largest heap operation to be completed with two more elements than the smallest heap). Correctly, you should add the top element of the largest heap to the smallest heap and pop it, and then add new elements to the largest heap, so as to maintain balance. A young girl.
    • Case 3: The smallest heap has one more element than the largest heap, which is consistent with the above idea!

Complete code:

#include <iostream>
#include <stack>
#include <queue>
using namespace std;

class MedianFinder {
    
    
public:
    /** initialize your data structure here. */
    MedianFinder() {
    
    
    }

    // 数据加入及最大堆和最小堆的维护
    void addNum(int num) {
    
    
        if (big_heap.empty()) {
    
    
            big_heap.push(num);
            return;
        }
        // 情况1
        if (big_heap.size() == small_heap.size()) {
    
    
            if (num < big_heap.top()) {
    
    
                big_heap.push(num);
            }
            else {
    
    
                small_heap.push(num);
            }
        }
        // 情况2
        else if (big_heap.size() > small_heap.size()) {
    
    
            if (num > big_heap.top())
                small_heap.push(num);
            else {
    
    
                small_heap.push(big_heap.top());
                big_heap.pop();
                big_heap.push(num);
            }
        }
        // 情况3
        else if (big_heap.size() < small_heap.size()) {
    
    
            if (num < small_heap.top())
                big_heap.push(num);
            else {
    
    
                big_heap.push(small_heap.top());
                small_heap.pop();
                small_heap.push(num);
            }
        }
    }

    // 求中位数
    double findMedian() {
    
    
        if (big_heap.size() == small_heap.size()) {
    
    
            return (double(big_heap.top()) + small_heap.top()) / 2.0;
        }
        else if (big_heap.size() > small_heap.size())
            return big_heap.top();
        return small_heap.top();
    }
private:
    priority_queue<int, vector<int>, less<int>> big_heap;  // 构造最大堆
    priority_queue<int, vector<int>, greater<int>> small_heap; // 构造最小堆
};

// 以下为测试
int main() {
    
    
    
    MedianFinder m;
    m.addNum(1);
    m.addNum(2);
    cout << m.findMedian() << endl;
    m.addNum(3);
    cout << m.findMedian() << endl;
    return 0;
}

result:

1.5
2

ps: This article is a note for the Little Elephant Academy tutorial: https://www.bilibili.com/video/BV1GW411Q77S?t=7029&p=2
LeetCode title number: 215,295

Guess you like

Origin blog.csdn.net/weixin_44427114/article/details/107911651