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 fromnums
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 integerval
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