最大堆:priority_queue
最小堆:priority_queue
如果使用 priority_queue
最小堆会在一些图算法中应用,比如prim,dijkstra算法等,参考链接:
最小生成树-kruskal-prim(《算法导论3rd-P362》)_hclbeloved的博客-CSDN博客
单源最短路径(《算法导论3rd-P374》)_hclbeloved的博客-CSDN博客
347. 前 K 个高频元素
剑指 Offer II 060. 出现频率最高的 k 个数字
class Solution {
public:
vector topKFrequent(vector& nums, int k) {
unordered_map occur;
for (auto& i : nums)
occur[i]++;
struct cmp
{
bool operator()(const pair& m, const pair& n)
{
return m.second > n.second;
}
};
// pair 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
priority_queue, vector>, cmp> minHeap;
for (auto& item : occur)
{
if (minHeap.size() >= k)
{
if (item.second > minHeap.top().second)
{
minHeap.pop();
minHeap.push({item.first, item.second});
}
}
else
{
minHeap.push({item.first, item.second});
}
}
vector r;
while (!minHeap.empty())
{
r.emplace_back(minHeap.top().first);
minHeap.pop();
}
return r;
}
};
215. 数组中的第K个最大元素
class Solution {
public:
int findKthLargest(vector& nums, int k) {
//方法一:借助快速排序的思路,o(n)
// return partition(nums, 0, nums.size()-1, k);
//借助于堆排序,这里使用的是容量为k的最小堆,o(nlogk)
priority_queue,greater> minHeap;
for(auto& i:nums)
{
if (minHeap.size() < k)
{
minHeap.push(i);
}
else
{
if (i > minHeap.top())
{
minHeap.pop();
minHeap.push(i);
}
}
}
return minHeap.top();
}
//第K(K从1开始索引)大就是第 size+1-K 小
//对应的从0开始的索引就是 size-K
int partition(vector& nums, int p, int r, int k)
{
int x = nums[r];
int j = p-1;
for(int i=p;i<=r-1;++i)
{
if (nums[i] <= x)
std::swap(nums[++j], nums[i]);
}
std::swap(nums[++j], nums[r]);
if (j < nums.size() - k)
{
return partition(nums, j+1, r, k);
}
else if (j > nums.size() - k)
{
return partition(nums, p, j-1, k);
}
else
{
return nums[j];
}
}
};
295. 数据流的中位数
class MedianFinder {
public:
std::priority_queue, greater> minHeap;
std::priority_queue, less> maxHeap;
/** initialize your data structure here. */
MedianFinder() {
}
void addNum(int num) {
if (maxHeap.size() > minHeap.size())
{
int top = maxHeap.top();
if (num > top)
{
minHeap.push(num);
}
else
{
maxHeap.pop();
minHeap.push(top);
maxHeap.push(num);
}
}
else
{
if (!minHeap.empty())
{
int top = minHeap.top();
if (num > top)
{
minHeap.pop();
minHeap.push(num);
maxHeap.push(top);
}
else
{
maxHeap.push(num);
}
}
else
{
maxHeap.push(num);
}
}
}
double findMedian() {
if (maxHeap.size() > minHeap.size())
{
return maxHeap.top();
}
else
{
if (!maxHeap.empty())
{
return (maxHeap.top() + minHeap.top()) / 2.0;
}
else
{
return 0.0;
}
}
}
};
剑指 Offer 40. 最小的k个数
class Solution {
public:
vector getLeastNumbers(vector& arr, int k) {
//方法二:使用堆排序,使用的是最大堆
if (k <= 0)
return vector{};
priority_queue maxHeap;
for (auto& i:arr)
{
if (maxHeap.size() < k)
{
maxHeap.push(i);
}
else
{
if (i < maxHeap.top())
{
maxHeap.pop();
maxHeap.push(i);
}
}
}
vector r;
while (!maxHeap.empty())
{
r.push_back(maxHeap.top());
maxHeap.pop();
}
return r;
}
};
451. 根据字符出现频率排序
//类似题目:https://leetcode-cn.com/problems/g5c51o/
class Solution {
public:
string frequencySort(string s) {
unordered_map occur;
for (auto& i : s)
occur[i]++;
struct cmp
{
bool operator()(const pair& m, const pair& n)
{
return m.second < n.second;
}
};
// pair 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
priority_queue, vector>, cmp> maxHeap;
for (auto& item : occur)
maxHeap.push({item.first, item.second});
string r;
while (!maxHeap.empty())
{
r.append(maxHeap.top().second, maxHeap.top().first);
maxHeap.pop();
}
return r;
}
};
剑指 Offer II 061. 和最小的 k 个数对
373. 查找和最小的 K 对数字
class Solution {
public:
vector> kSmallestPairs(vector& nums1, vector& nums2, int k) {
//方法一:最大堆
//https://leetcode-cn.com/problems/qn8gGX/solution/jian-zhi-offer-2-mian-shi-ti-61-shu-zhon-d9q5/
// struct cmp
// {
// bool operator()(const pair& a, const pair& b)
// {
// return (a.first+a.second < b.first+b.second);
// }
// };
// priority_queue, vector>, cmp> maxHeap;
// for (int i = 0; i < nums1.size() && i < k; ++i)
// {
// for (int j = 0; j < nums2.size() && j < k; ++j)
// {
// if (maxHeap.size() < k)
// {
// maxHeap.push({nums1[i], nums2[j]});
// }
// else if (nums1[i] + nums2[j] < maxHeap.top().first + maxHeap.top().second)
// {
// maxHeap.pop();
// maxHeap.push({nums1[i], nums2[j]});
// }
// }
// }
// vector> r;
// while (!maxHeap.empty())
// {
// r.push_back({maxHeap.top().first, maxHeap.top().second});
// maxHeap.pop();
// }
// return r;
//方法二: 最小堆
//https://leetcode-cn.com/problems/qn8gGX/solution/jian-zhi-offer-2-mian-shi-ti-61-shu-zhon-d9q5/
auto cmp = [&](const pair& lhs, const pair& rhs)
{
return nums1[lhs.first] + nums2[lhs.second] > nums1[rhs.first] + nums2[rhs.second];
};
priority_queue, vector>, decltype(cmp)> minHeap(cmp);
for (int i = 0; i < k && i < nums1.size(); ++i)
{
minHeap.push({i, 0});
}
vector> r;
while (k-- > 0 && !minHeap.empty())
{
auto ids = minHeap.top();
minHeap.pop();
r.push_back({nums1[ids.first], nums2[ids.second]});
if (ids.second < nums2.size() - 1)
{
minHeap.push({ids.first, ids.second + 1});
}
}
return r;
}
};
剑指 Offer II 063. 替换单词
648. 单词替换
// class Solution {
// public:
// string replaceWords(vector& dictionary, string sentence) {
// //最大堆
// auto cmp = [](const string& a, const string& b)->bool
// {
// return a.length() < b.length();
// };
// priority_queue, decltype(cmp)> maxHeap(cmp);
// for (auto& str:dictionary)
// maxHeap.push(str);
// int pos = -1, start = 0;
// vector v;
// while((pos=sentence.find_first_of(' ', start)) != string::npos)
// {
// v.push_back(sentence.substr(start, pos-start));
// start = pos + 1;
// }
// string str = sentence.substr(start);
// if (!str.empty())
// v.push_back(str);
// while (!maxHeap.empty())
// {
// const string& pattern = maxHeap.top();
// for (auto& str : v)
// {
// // if (KnuthMorrisPratt(str, pattern) != -1)
// if (KnuthMorrisPratt(str, pattern) == 0)
// {
// str = pattern;
// }
// }
// maxHeap.pop();
// }
// string res;
// for (auto& str : v)
// {
// if (res.empty())
// {
// res.append(str);
// }
// else
// {
// res.append(1,' ').append(str);
// }
// }
// return res;
// }
// // pattern表示模式串
// vector getNexts(const string& pattern)
// {
// int n = pattern.length();
// vector next(n, 0);
// next[0] = -1;
// int k = -1;
// //求解所有好前缀的最长可匹配前缀子串,最长的好前缀为[0, n-2],所以下面可以修改为: i < n - 1
// //for (int i = 1; i < n; ++i) //这里就算是计算了next[n-1]其实也用不到,所以这里就是计算了也没影响
// for (int i = 1; i < n - 1; ++i)
// {
// while (k != -1 && pattern[k + 1] != pattern[i])
// {
// k = next[k];
// }
// if (pattern[k + 1] == pattern[i])
// {
// ++k;
// }
// next[i] = k;
// }
// return next;
// }
// // src, pattern分别是主串和模式串
// int KnuthMorrisPratt(const string& src, const string& pattern)
// {
// int patternLen = pattern.length();
// vector next = getNexts(pattern);
// int j = 0, n = src.length();
// for (int i = 0; i < n; ++i)
// {
// while (j > 0 && src[i] != pattern[j]) // 一直找到a[i]和b[j]
// {
// //next[j - 1]表示模式串中最长可匹配前缀子串的结尾字符的下标,那么就可将主串中索引 i 处的坏字符开始与next[j - 1] + 1字符进行比较
// j = next[j - 1] + 1;//当j=0时退出循环,表示下一轮主串开始从索引 i+1 处与模式串(从头开始也就是j=0)开始新一轮的比较
// }
// if (src[i] == pattern[j])
// {
// ++j;
// }
// if (j == patternLen) // 找到匹配模式串的了
// {
// //src[r, i]恰好等于pattern,所以 i - r + 1 = pattern, r = i + 1 - pattern
// return i - patternLen + 1;
// }
// }
// return -1;
// }
// };
class Solution {
public:
string replaceWords(vector& dictionary, string sentence) {
//最大堆
auto cmp = [](const string& a, const string& b)->bool
{
return a.length() < b.length();
};
priority_queue, decltype(cmp)> maxHeap(cmp);
for (auto& str:dictionary)
maxHeap.push(str);
int pos = -1, start = 0;
vector v;
while((pos=sentence.find_first_of(' ', start)) != string::npos)
{
v.push_back(sentence.substr(start, pos-start));
start = pos + 1;
}
string str = sentence.substr(start);
if (!str.empty())
v.push_back(str);
while (!maxHeap.empty())
{
const string& pattern = maxHeap.top();
for (auto& str : v)
{
if (str.substr(0, pattern.length()).compare(pattern) == 0)
{
str = pattern;
}
}
maxHeap.pop();
}
string res;
for (auto& str : v)
{
if (res.empty())
{
res.append(str);
}
else
{
res.append(1,' ').append(str);
}
}
return res;
}
};
剑指 Offer II 059. 数据流的第 K 大数值
703. 数据流中的第 K 大元素
//使用含有k个元素的最小堆
class KthLargest {
public:
int n;
priority_queue, greater> minHeap;
KthLargest(int k, vector& nums) {
n = k;
for (auto& i:nums)
{
if (minHeap.size() < k)
{
minHeap.push(i);
}
else
{
if (i > minHeap.top())
{
minHeap.pop();
minHeap.push(i);
}
}
}
}
int add(int val) {
if (minHeap.size() < n)
{
minHeap.push(val);
}
else
{
if (val > minHeap.top())
{
minHeap.pop();
minHeap.push(val);
}
}
return minHeap.top();
}
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/
2.9
2.10
2.11
2.12
2.13
2.14
2.15
2.16
2.17
2.18
2.19
2.20
2.21