Algo_9_Heap
學習算法
Heap
- 特色:具有最大堆和最小堆
- 最大堆:跟節點永遠是最大值
- 最小堆:跟節點永遠是最小值
二叉堆
- 概念:二叉堆是一顆完全二叉樹,樹的每層都會滿,除了最後一層不一定
i > 1
的節點,其父節點i/2
- 如果
2i>n
那麼i節點沒有孩子,如果2i+1>n
那麼節點i沒有右孩子 - 如果i有孩子,那麼左孩子為2i,右孩子為2i+1
- 操作:
- 進堆:每次把元素放進堆,使跟節點保持最小(最小堆)
- 出堆:每次取出的堆頂,也就是最小值。同時調整堆,使新的堆頂最小
實現
- 可以直接使用
priority_queue
,因為是由堆實現的priority_queue
默認由小排到大,可以使用priority_queue<T,vector<T>,geather<>>
來自訂排序geather
為struct,可以自定義,默認由小到大,以下使用cmp代替原本的geather
struct cmp { bool operator()(pair<int,int>a,pair<int,int>b){ return a.second < b.second; } };
- 也可以使用數組實現
Leetcode 1046
class Solution {
public:
int lastStoneWeight(vector<int>& stones) {
priority_queue<int> maxHeap;
for(int stone : stones){
maxHeap.push(stone);
}
while(maxHeap.size() > 1){
int x = maxHeap.top();
maxHeap.pop();
int y = maxHeap.top();
maxHeap.pop();
if(x != y){
maxHeap.push(x-y);
}
}
return maxHeap.size() > 0 ? maxHeap.top() : 0;
}
};
Leetcode 215
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> pq;
for(int n : nums) pq.push(n);
for(int i=0;i<k-1;i++){
pq.pop();
}
return pq.top();
}
};
Leetcode 347
struct cmp {
bool operator()(pair<int,int>a,pair<int,int>b){
return a.second < b.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> mp;
for(int n : nums ) mp[n]++;
priority_queue<pair<int,int>,vector<pair<int,int>>,cmp> pq;
for(auto m : mp) {
pq.push({m.first,m.second});
}
vector<int> ans;
while(k-- > 0){
ans.push_back(pq.top().first);
pq.pop();
}
return ans;
}
第二種解法
vector<int> topKFrequent(vector<int>& nums, int k){
unordered_map<int,int> mp;
for(int n : nums ) mp[n]++;
vector<vector<int>> vc(nums.size()+1);
for(auto m : mp) {
vc[m.second].push_back(m.first);
}
vector<int> ans;
for(int i=vc.size()-1;i>=0;i--){
for(int v : vc[i]){
ans.push_back(v);
if(ans.size()==k) return ans;;
}
}
return {};
}
Leetcode 973
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int k) {
priority_queue<pair<int,vector<int>>> pq;
for(vector<int> point : points) {
int x = point[0];
int y = point[1];
int dis = x*x + y*y;
pq.push({dis,point});
if(pq.size() > k) pq.pop();
}
vector<vector<int>> ans;
while(!pq.empty()){
pair<int,vector<int>> top = pq.top();
ans.push_back(top.second);
pq.pop();
}
return ans;
}
};
Leetcode 23
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<int,vector<int>,greater<int>> pq;
ListNode* head = new ListNode();
ListNode* dummy = head;
for(int i=0;i<lists.size();i++){
ListNode* l = lists[i];
while(l != nullptr) {
pq.push(l->val);
l = l->next;
}
}
while(!pq.empty()){
int top = pq.top();
dummy->next = new ListNode(top);
dummy = dummy->next;
pq.pop();
}
return head->next;
}
};