求前K個最大數,或第K個最大數或第K大頻率的單詞類似問題小結

求前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;
                }
            }
        }
    };
    
};


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章