I have the same thought with you. I think this is O(nlogk) time and O(n) space. One suggestion is that since you have defined a class for comparing you do not need to rewrite the comparing function again in your for loop.

Here is my code.

class Solution {
struct cmp {
bool operator()(const pair<int, string>& one, const pair<int, string>& two) const {
return one.first > two.first ||(one.first == two.first && one.second < two.second);
}
};
public:
vector<string> topKFrequent(vector<string>& words, int k) {
unordered_map<string, int> word2Freq;
vector<string> res(k);
for (auto& w : words) word2Freq[w]++;
priority_queue<pair<int, string>, vector<pair<int, string> >, cmp> heap;
cmp obj;
for (auto it = word2Freq.begin(); it != word2Freq.end(); it++) {
pair<int, string> cur = make_pair(it->second, it->first);
if (heap.size() < k) {
heap.push(cur);
} else if (!obj(heap.top(), cur)) {
heap.pop();
heap.push(cur);
}
}
int it = k - 1;
while (!heap.empty()) {
res[it--] = heap.top().second;
heap.pop();
}
return res;
}
};