NC97 字符串出现次数的TopK问题(堆)

描述
给定一个字符串数组,再给定整数k,请返回出现次数前k名的字符串和对应的次数。
返回的答案应该按字符串出现频率由高到低排序。如果不同的字符串有相同出现频率,按字典序排序。
对于两个字符串,大小关系取决于两个字符串从左到右第一个不同字符的 ASCII 值的大小关系。比如"ah1x"小于"ahb",“231”<”32“
字符仅包含数字和字母

如果字符串数组长度为N,时间复杂度请达到O(NlogK)

示例1
输入:[“a”,“b”,“c”,“b”],2
返回值:[[“b”,“2”],[“a”,“1”]]
说明:
"b"出现了2次,记[“b”,“2”],"a"与"c"各出现1次,但是a字典序在c前面,记[“a”,“1”],最后返回[[“b”,“2”],[“a”,“1”]]

示例2
输入:[“123”,“123”,“231”,“32”],2
返回值:[[“123”,“2”],[“231”,“1”]]
说明:
"123"出现了2次,记[“123”,“2”],"231"与"32"各出现1次,但是"231"字典序在"32"前面,记[“231”,“1”],最后返回[[“123”,“2”],[“231”,“1”]]
示例3
输入:[“abcd”,“abcd”,“abcd”,“pwb2”,“abcd”,“pwb2”,“p12”],3
返回值:[[“abcd”,“4”],[“pwb2”,“2”],[“p12”,“1”]]

  • 首先使用hash表对所有的字符串集合计数,之后将strings按照自定义的排序顺序(出现次数不同,次数大的在前面;出现次数相同,字典序小的在前面)进行排序。
  • 将strings排好序之后,根据给定的k值筛选前k个元素,因为按照这样的顺序排序,相当于升序排列,是个小根堆。元素个数不够k个,那么直接放进去,如果大于k个就需要将堆顶元素弹出,然后再将该元素放入。
class Solution {
public:
    struct Cmp{
        bool operator() (pair<string,int> &a,pair<string,int> &b){
            if(a.second!=b.second) return a.second>b.second;
            return a.first<b.first;
        }
    };
    vector<vector<string> > topKstrings(vector<string>& strings, int k) {
        // write code here
        unordered_map<string,int> hash;
        for(auto c:strings) hash[c]++;
        priority_queue<pair<string,int>,vector<pair<string,int>>,Cmp> q;
        for(auto c:hash)
        {
            if(q.size()<k) q.push(c);
            else 
            {
                q.push(c);
                q.pop();
            }
        }
       // k=min(k,(int)hash.size());
        vector<vector<string>> ans(k,vector<string>());
        while(!q.empty())
        {
            --k;
            ans[k].push_back(q.top().first);
            ans[k].push_back(to_string(q.top().second));
            q.pop();
        }
        return ans;
    }
};

你可能感兴趣的:(牛客刷题)