Data structure notes--priority queue (large and small root heap) classic question type

1--The maximum profit of the project

Title description:

        Input: positive number array costs, costs[i] indicates the cost of item i; positive number array profits, profits[i] indicates the cost of item i; positive number k means that only k items can be completed serially; m means owned Funds, which are updated immediately after each completed project (original funds + profit);

        Output: Solve the final maximum profit;

Main ideas:

        The small root heap stores all items, and the large root heap stores the items that can be carried out;

        Every time the items unlocked from the small root pile are added to the big root pile, the project with the highest profit in the big root pile is given priority;

#include <iostream>
#include <vector>
#include <queue>

struct project{
    project(int c, int p) : cost(c), profit(p) {}
    int cost;
    int profit;
};

class cmp1{
public:
    bool operator()(project* a, project* b){
        return a->cost > b->cost;
    }
};

struct cmp2{
    bool operator()(project* a, project* b){
        return a->profit < b->profit;
    }
};

class Solution{
public:
    int findMaxCapital(int m, int k, std::vector<int> costs, std::vector<int> profits){
        std::priority_queue<project*, std::vector<project*>, cmp1> minCostQ;
        std::priority_queue<project*, std::vector<project*>, cmp2> maxProfitQ;

        // 按cost按从小到大排序项目
        for(int i = 0; i < profits.size(); i++){
            minCostQ.push(new project(costs[i], profits[i]));
        }
        for(int i = 0; i < k; i++){
            while(!minCostQ.empty() && minCostQ.top()->cost <= m){
                // 可以解锁新的项目
                maxProfitQ.push(minCostQ.top());
                minCostQ.pop();
            }
            if(maxProfitQ.empty()) return m; // 无法解锁新的项目,直接返回
            
            // 更新资金
            m += maxProfitQ.top()->profit;
            maxProfitQ.pop();
        }
        return m;
    }
};

int main(int argc, char *argv[]){
    int m = 1;
    int k = 2;
    std::vector<int> costs = {1, 1, 2, 2, 3, 4};
    std::vector<int> profits = {1, 4, 3, 7, 2, 10};
    Solution S1;
    int res = S1.findMaxCapital(m, k, costs, profits);
    std::cout << res << std::endl; 
}

2--The median of the data stream

Main ideas:

        Use the big root heap and the small root heap to store data respectively. Every time you add a piece of data, first add the data to the big root heap, then pop the data out and add it to the small root heap;

        When there is a difference of 2 between the value of the small root heap and the value of the large root heap, the data is popped from the small root heap and added to the large root heap, keeping the capacity difference between the two root heaps not exceeding;

        According to whether the amount of added data is even or odd, return the corresponding median;

#include <iostream>
#include <queue>

class MedianFinder {
public:
    MedianFinder() {

    }
    
    void addNum(int num) {
        maxQ.push(num);
        minQ.push(maxQ.top());
        maxQ.pop();
        if(minQ.size() - maxQ.size() > 1){
            maxQ.push(minQ.top());
            minQ.pop();
        }
    }
    
    double findMedian() {
        // 奇数
        if((maxQ.size() + minQ.size()) % 2 != 0) return minQ.top();
        // 偶数
        else return( (maxQ.top() + minQ.top()) / 2.0);
    }
private:
    std::priority_queue<int, std::vector<int>, std::greater<int>> minQ;
    std::priority_queue<int, std::vector<int>, std::less<int>> maxQ;
};

int main(int argc, char *argv[]){
    MedianFinder S1;
    S1.addNum(1);
    S1.addNum(2);
    S1.addNum(3);
    S1.addNum(4);
    S1.addNum(5);
    double res = S1.findMedian();
    std::cout << res << std::endl;
}

Guess you like

Origin blog.csdn.net/weixin_43863869/article/details/132273931