找到顶级K频繁的单词

时间:2018-01-19 22:20:59

标签: c++ algorithm

我正在尝试从Leetcode网站解决问题 - Finding top K frequent words

  

给定一个非空的单词列表,返回k个最常见的元素   您的答案应按频率从最高到最低排序。如果两个单词的频率相同,则字母顺序较低的单词首先出现。例如:如果输入是:["","日","是","晴天",""&# 34;,"","","晴","","是"],k = 4,然后输出应该是:["","是","晴天","天"]。

其中一个受欢迎的解决方案如下:

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        unordered_map<string,int> dict;
        for(const string& s:words) dict[s]++;

        priority_queue<pair<string,int>, vector<pair<string,int>>, Comp> pq;
        for(const auto& pa:dict) {
            pq.push(pa);
            if(pq.size()>k) pq.pop();
        }    

        vector<string> result;
        while(!pq.empty()) {
            result.push_back(pq.top().first);
            pq.pop();
        }
        reverse(result.begin(),result.end());    
        return result;    
    }
private:
    struct Comp {
        Comp() {}
        ~Comp() {}
        bool operator()(const pair<string,int>& a, const pair<string,int>& b) {
            return a.second>b.second || (a.second==b.second && a.first<b.first);
        }
    };

};

我想更好地理解它并提出一些问题:

  1. pq.size()>k时,我们pop() - 这不正确,因为在这种情况下,我们正在失去最高频率元素?我是这么认为的,因为根据比较器,频率较高的元素(在频率相等的情况下按字母顺序较小)会插入优先级队列的顶部。
  2. 在优先级队列的情况下,当我们实现自己的比较器时,我们必须传递第二个参数(表示要使用的Container),但是当我们使用默认比较器时不需要 - 为什么呢?我的意思是,根据我将要存储的值的类型(第一个参数,在这种情况下为pair<string, int>),可以自动推断默认容器类型吗?
  3. 如果是pq.push(pa);pa的确切类型是什么?我想知道因为pq包含vector<pair<string, int>>,但dict只包含string(映射到int中的频率)。如何使用auto自动将string密钥映射到其int频率以插入优先级队列?
  4. 为这么长的问题道歉。谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

  1. 您并没有真正取出频率最高的那些因为有序被反转到优先级队列中。事实上,最后有一个反向调用以 right 顺序输出元素。请注意,它在文档中已明确说明。
  2. 来自docs

      

    请注意,Compare参数的定义使其返回true   如果它的第一个参数出现在弱的第二个参数之前   排序。但是因为优先级队列输出最大的元素   首先,“之前”的元素实际上是最后输出的。那   是,队列的前面包含根据的“最后”元素   比较强加的弱序。

    1. pa的类型是unordered_map<string,int>::value_type中指定的std::pair<const string,int>类型。 事实上,unordered_map<K, V>::value_type的每个元素都是std::pair<const K, V>的typedef。由于priority_queue存储std::pair<string,int>,所以不会出现奇怪的事情。
    2. 希望这有帮助。