Priority Queue and Its Applications (LeetCode #2208 & LeetCode #895)

本文介绍了如何利用优先队列数据结构解决LeetCode中的数组减半问题,通过比较元素优先级和操作次数,展示了如何在最少操作下将数组总和减半。同时,讲解了如何设计频次栈来处理频繁元素的弹出问题,使用自定义triplet结构配合优先队列来高效管理频率和位置信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

We all should be very familiar with a simple queue, a data structure where its elements are in a FIFO (First In First Out) order. But, what if we want to jump to the queue? We want to push elements that can exit the queue earlier. Today, I present to you: priority queue.

A priority queue is just like a simple queue, but elements with a higher priority are placed in front of those that are not of that much importance. It can act as a max heap or an array with non-increasing elements.


LeetCode #2208

You are given an array nums of positive integers. In one operation, you can choose any number from nums and reduce it to exactly half the number. (Note that you may choose this reduced number in future operations.)

Return the minimum number of operations to reduce the sum of nums by at least half.

Intuitively, we have to start by reducing the maximum element by half and then check if the sum of the nums are already halved. We'll then repeat the entire process until the condition is satisfied. In here, in stead of sorting nums, we can simply use a priority queue to deal with the sorting:

priority_queue<int> q;

The push() method is the enqueue operation; The pop() method is the dequeue operation; The top() method retrieves the front of the queue(usually used to get the front element before calling pop() as pop() is a void function).

The above is a priority queue with greater elements place in front of those that are smaller. Below is the syntax if you want it to do the reverse:

priority_queue<int, vector<int>, greater<int> > q;

And here's my solution to the problem:

class Solution {
public:
    int halveArray(vector<int>& nums) {
        priority_queue<double> pnum;
        double sum = 0;
        for(int i = 0; i < nums.size(); i++){
            pnum.push(double(nums[i]));
            sum += nums[i];
        }
        double half = sum/2;
        int count = 0;
        while(sum > half){
            double max = pnum.top();
            pnum.pop();
            max /= 2;
            pnum.push(max);
            sum-=max;
            count ++;
        }
        return count;
    }
};

LeetCode #895

Design a stack-like data structure to push elements to the stack and pop the most frequent element from the stack.

Implement the FreqStack class:

  • FreqStack() constructs an empty frequency stack.
  • void push(int val) pushes an integer val onto the top of the stack.
  • int pop() removes and returns the most frequent element in the stack.
    • If there is a tie for the most frequent element, the element closest to the stack's top is removed and returned.

For this problem, we will be using a self-defined data structure to store the necessary information to be store in the priority queue:

typedef pair<int, pair<int, int>> triplet;

In this structure, we are defining a nested pair. The leftmost int represents the freq of an element, the middle one represents the number of elements inserted in the list (an ever-increasing value) and the rightmost one represents the value of the element. We can access those elements as the followings:

triplet t = {10, {2, 5}};
t.first;            // frequency
t.second.first;     // index
t.second.second;    // value

The priority will compare the first element in triplet. If equal values are encountered, it will then compare with their second element. With this in mind, each time an element is inserted, we will enqueue a new triplet into the priority queue specifying its frequency and its index for this insertion. When we need to access the top of this FreqStack, just dequeue the priority queue. The priority queue already helps us deal with the ordering.

class FreqStack {
    typedef pair<int, pair<int, int>> triplet;
    priority_queue<triplet> freqstack;
    unordered_map<int, int> freq_map;
    int n = 0;
public:
    FreqStack() {
    }
    
    void push(int val) {
        freq_map[val]++;
        freqstack.push({freq_map[val], {n, val}});
        n++;
    }
    
    int pop() {
        triplet tri = freqstack.top();
        freqstack.pop();
        freq_map[tri.second.second]--;
        return tri.second.second;
    }
};

Note that we also have an extra map to store the frequency of each element. It makes creating a new triplet easier.


Special thanks to Angus Gor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值