题目描述
有一个不为空且仅包含正整数的数组,找出其中出现频率最高的前 K 个数,时间复杂度必须在 O(n log n) 以内。
行数据包括两部分,一个正整数数组(数字间 ‘,’ 分隔)和一个正整数 K (1 ≤ K ≤ 数组长度),数组和 K 之间有一个空格。
输出包含前 K 个出现频率最高的数(出现频率相同时,较小的数在前),用 ', ’ 分隔,保证升序排列。
示例 1:
输入:1,1,1,2,2,3 2
输出:1,2
题解思路
首先遍历整个数组,并使用哈希表记录每个数字出现的次数,并形成一个「出现次数数组」。给「出现次数数组」排序。但由于可能有 O(N) 个不同的出现次数(其中 N 为原数组长度),故总的算法复杂度会达到 O(NlogN)。
复杂度分析:
- 时间复杂度:O(NlogN)。
- 空间复杂度:O(N)。
小米OJ:
代码实现:
#include <bits/stdc++.h>
using namespace std;
static bool cmp(const pair<int, int>& a, const pair<int, int>& b) {
if (a.second == b.second) {
return a.first < b.first;
}
return a.second > b.second;
}
string topKFrequent(vector<int>& nums, int k) {
map<int, int> m;
for (auto i : nums) {
m[i]++;
}
vector<pair<int, int>> v;
for (map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
v.push_back(pair<int, int>(it->first, it->second));
}
sort(v.begin(), v.end(), cmp);
string s;
for (int i = 0; i < k; ++i) {
if (i == 0) {
s += to_string(v[i].first);
}
else {
s += ',';
s += to_string(v[i].first);
}
}
return s;
}
int main() {
string s;
int k;
while (cin >> s >> k) {
vector<int> v;
while (s.size()) {
int n = s.find(',');
if (n == -1) {
break;
}
string str = s.substr(0, n);
int num = stoi(str);
v.push_back(num);
s = s.substr(n + 1);
}
int num = stoi(s);
v.push_back(num);
cout << topKFrequent(v, k) << endl;
}
return 0;
}
LeetCode:
代码实现:
class Solution {
static bool cmp(const pair<int, int>& a, const pair<int, int>& b) {
if (a.second == b.second) {
return a.first < b.first;
}
return a.second > b.second;
}
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int, int> m;
for (auto i : nums) {
m[i]++;
}
vector<pair<int, int>> v;
for (map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
v.push_back(pair<int, int>(it->first, it->second));
}
sort(v.begin(), v.end(), cmp);
vector<int> res;
for (int i = 0; i < k; ++i) {
res.push_back(v[i].first);
}
return res;
}
};