求前K個最大數,最小數,第K個最大數,或者 出現頻率爲第K大的單詞是哪個 此類問題,首先想到的就是排序,但是求第K最大而已,並不要求完全有序,所以 想到了 大頂堆 和小頂堆
我們可以用到 優先級隊列 priority_queue,它實際上是一個隊列,但是它的功能是始終保持隊首元素是當前元素的最大值
定義:priority_queue<Type, Container, Functional>
Type 就是數據類型,Container 就是容器類型(Container必須是用數組實現的容器,比如vector,deque等等,但不能用 list。STL裏面默認用的是vector),Functional 是仿函數,決定了優先隊列的 比較方式
默認爲大頂堆:priority_queue<int,vector<int>,less<int>>
當然也可以自定義類型然後自定義相匹配的仿函數
1.首選由簡單的例題着手:
本題要求數組中第K大的數是多少?
第一想法是進行排序,然後選擇合適位置處的元素即可
但是要求是求第K大元素,並不要求對數組進行排序
所以我們只要知道前K個最大元素即可,而對於他們的順序無關緊要,所以就可以用到優先級隊列priority_queue
將數組元素逐漸壓入priority_queue,當優先級隊列內的元素 大於 (所有元素個數 - k)時,即優先級隊列頂端中一定是前K個元素中的某一個了
取出頂端元素壓入 數組中,然後找到數組中的最小元素,即爲全部元素中的第K大元素
class Solution {
public:
int findKthLargest(vector<int>& nums, int k)
{
vector<int> restmp;
priority_queue<int> pq;//優先級隊列
for(auto i : nums)
{
pq.push(i);
if(pq.size() > nums.size()-k)
{
restmp.push_back(pq.top());
pq.pop();
}
}
int kmin =INT_MAX;
for(int i : restmp)
{
if(i <= kmin)
{
kmin = i;
}
}
return kmin;
}
};
2.求數組中,出現頻率位於前K次的元素
這題目也不難,容易想到的就是用 哈希map來統計每一個元素出現的次數
然後用優先級隊列,但由於 比第一題多了 要考慮的頻率,所以我們採用 對組 pair<int,int>容器
來記錄各個元素出現的頻率以及對應的元素。
然後求前K個,用默認的大頂堆即可
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k)
{
unordered_map<int,int> map;
vector<int> res;
for(int i = 0; i < nums.size(); i++)//統計每個元素的出現的頻率
{
map[nums[i]]++;
}
priority_queue<pair<int,int>> pq; //用大頂堆來記錄 頻率和對應元素,
//用pair的第一個元素代表頻率,第二個元素代表對應該頻率對應的元素
for(auto it = map.begin(); it != map.end(); it++)
{
pq.push(make_pair(it->second,it->first));
if(pq.size() > map.size()-k)
{
res.push_back(pq.top().second);
pq.pop();
}
}
return res;
}
};
3.求數組中出現頻率爲與前K的單詞
本來,這道題目和第二題是一樣的,只不過把 數據元素 換位 單詞元素即可
雖然要求 單詞的頻率求出現最多的前K個,但是當兩個單詞出現頻率相同時,並不是要求隨意擺放,結果中要求
頻率相等時,單詞按字典順序擺放,即升序擺放
所以,問題出現了,頻率按降序,頻率相同時,單詞按升序
顯然,要定義自己的仿函數
由於也是用對組 pair<int,string>來記錄頻率和對應的單詞;對組中第一個元素代表頻率
所以,仿函數
struct fun
{
bool operator()(pair<int,string>& p1, pair<int,string>& p2)
{
if(p1.first < p2.first)//這樣記憶吧,小於號代表降序,大於到代表升序
{
return true;
}
else if(p1.first > p2.first)
{
return false;
}
else
{
if(p1.second > p2.second)
{
return true;
}
else
{
return false;
}
}
}
};
所以完整程序如下:
class Solution {
public:
vector<string> topKFrequent(vector<string>& words, int k)
{
vector<string> res;
unordered_map<string,int> map;
for(auto word : words)
{
map[word]++;
}
priority_queue<pair<int,string>,vector<pair<int,string>>,fun> pq;
for(auto it = map.begin(); it != map.end(); it++)
{
pq.push(make_pair(it->second,it->first));
}
while(pq.size() > map.size()-k)
{
res.push_back(pq.top().second);
pq.pop();
}
return res;
}
private:
struct fun
{
bool operator()(pair<int,string>& p1, pair<int,string>& p2)
{
if(p1.first < p2.first)//這樣記憶吧,小於號代表降序,大於到代表升序
{
return true;
}
else if(p1.first > p2.first)
{
return false;
}
else
{
if(p1.second > p2.second)
{
return true;
}
else
{
return false;
}
}
}
};
};