优先级队列的应用
第一题:

题解思路:
1、建立降序的优先级队列(底层是通过大堆来实现);
2、取最大的两个数来相减得到的结果再加入到优先级队列中(优先级队列会自动的排序);
3、返回队列的头部或者0即可;
题解代码:
class Solution {
public:
int lastStoneWeight(vector<int>& stones) {
// 创建大堆
priority_queue<int> heap;
//
for (auto& e : stones)
heap.push(e);
// 碰撞操作
while (heap.size() > 1) {
// 取队顶元素
int a = heap.top();
heap.pop();
// 取第二大的
int b = heap.top();
heap.pop();
if (a > b) {
heap.push(a - b);
}
}
return heap.size()?heap.top():0;
}
};
第二题:
题解思路:
题解代码:
class KthLargest {
priority_queue<int, vector<int>, greater<int>> heap;
int _k;
public:
KthLargest(int k, vector<int>& nums) {
_k = k;
for (auto& e : nums) {
heap.push(e);
if (heap.size() > _k) {
heap.pop();
}
}
}
int add(int val) {
heap.push(val);
if (heap.size() > _k)
heap.pop();
return heap.top();
}
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/
小结:
回答为什么要第k大,建小堆,第K小,建大堆的问题?
其实可以从上面的代码能够看出,return(返回) 的是heap.top()元素;就是说,第K大或者第k小,都是从后面往前数的,也即,升序的序列(小堆),从后往前数才能数到第K大的元素,而降序的序列(大堆),从后往前数才能数到第K小的元素;-------这就是为什么建大堆找K小,建小堆找第K大的原因。
第三题:
解题思路:
1、建立hash表统计次数;
2、建立优先级队列,并根据要求(次数按小堆,string按大堆)重写仿函数;
3、提取队列中的top( )按照升序排列;
注意的细节:
1、队列中我们存pair<string,int>这个组合;
2、cmp中,次数int要求是前k大,就说明是升序排列,建小堆;
3、 对应的,当次数相同的时候,按照的是string中的字母顺序的前后(注意,字母是按ASCII码的大小来排列,值越大越靠前,值小的在后面)说明是降序排列,建大堆;
解题代码:
class Solution {
typedef pair<string, int> PSI;
// 实现自定的仿函数
struct cmp {
bool operator()(const PSI& a, const PSI& b) {
if (a.second ==
b.second) { // 次数相同,按字母的asc码的降序,建大堆(小的往下沉)
return a.first < b.first;
}
// 次数不同就按次数的升序,前k个最大的,就是升序,建小堆(将大的往下沉)
return a.second > b.second;
}
};
public:
vector<string> topKFrequent(vector<string>& words, int k) {
// hash表统计次数
unordered_map<string, int> hash;
for (auto& e : words) {
hash[e]++;
}
// 创建一个大小为k的优先级队列
priority_queue<PSI, vector<PSI>, cmp> heap;
// 主逻辑
// 将hash表中所有的pair值存入到队列中
for (auto& psi : hash) {
heap.push(psi);
if (heap.size() > k)
heap.pop();
}
// 到这heap.top()是k个中次数最小的;而要求返回的数组中的从前往后是一次增大的;
vector<string> ret(k);
for (int i = k - 1; i >= 0; i--) {
ret[i] = heap.top().first;
heap.pop();
}
return ret;
}
};
小结:
1、优先级队列就是大堆小堆的包装,常用来处理topK问题;
2、求K大就建小堆,队列是升序排列,优先级队列的top()是K个当中最小的;
3、求K小就建大堆,队列是将序排列,优先级队列的top()是K个当中最大的;
4、只有栈和优先级队列才用的是top(),而普通的队列queue只有front():
·取栈顶元素用top();
·取优先级队列中的队头元素用top();
·取队列中的队头元素用front();