2020年9月2日 周三 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】
本文目录
1. 优先级队列(最小堆)2. 快速选择(快排的优化)3. 桶排序
LeetCode 347. 前K个高频元素
本题可看作 求前k个最大元素 的拓展,先用哈希表统计出每个元素出现的频率,然后对频率进行排序,求出前k个最大的频率,返回频率对应的值即可。
1. 优先级队列(最小堆)
class Solution {
public:
vector
<int> topKFrequent(vector
<int>& nums
, int k
) {
unordered_map
<int,int> map
;
for(auto num
:nums
)
++map
[num
];
priority_queue
<pair
<int,int>, vector
<pair
<int,int>>, greater
<pair
<int,int>> > pq
;
for(auto it
:map
){
if(pq
.size()==k
){
if(pq
.top().first
<it
.second
){
pq
.pop();
pq
.push(make_pair(it
.second
,it
.first
));
}
}
else pq
.push(make_pair(it
.second
,it
.first
));
}
vector
<int> res
;
while(!pq
.empty()){
res
.emplace_back(pq
.top().second
);
pq
.pop();
}
return res
;
}
};
时间复杂度:
O
(
n
log
k
)
O\left( {n\log k} \right)
O(nlogk) 证明过程:
log
1
+
log
2
+
.
.
.
+
log
k
⏟
k
+
log
k
+
.
.
.
+
log
k
⏟
n
−
k
=
log
k
!
+
(
n
−
k
)
log
k
≤
log
k
k
+
(
n
−
k
)
log
k
=
n
log
k
\underbrace {\log 1 + \log 2 + ... + \log k}_{k} + \underbrace {\log k + ...{\rm{ + }}\log k}_{n - k}{\rm{ = }}\log k! + \left( {n - k} \right)\log k \le \log {k^k} + \left( {n - k} \right)\log k = n\log k
k
log1+log2+...+logk+n−k
logk+...+logk=logk!+(n−k)logk≤logkk+(n−k)logk=nlogk空间复杂度:
O
(
n
)
O\left( {n} \right)
O(n)
2. 快速选择(快排的优化)
class Solution {
public:
vector
<int> topKFrequent(vector
<int>& nums
, int k
) {
unordered_map
<int,int> map
;
for(auto num
:nums
)
++map
[num
];
vector
<pair
<int,int>> freq
;
for(auto it
:map
)
freq
.emplace_back(make_pair(it
.first
,it
.second
));
int len
= freq
.size();
quickSelect(freq
,0,len
-1,len
-k
);
vector
<int> res
;
for(int i
=len
-k
;i
<len
;++i
)
res
.emplace_back(freq
[i
].first
);
return res
;
}
void quickSelect(vector
<pair
<int,int>>& nums
, int l
, int r
, int k
){
int rand_idx
= rand() % (r
-l
+1) + l
;
swap(nums
[l
],nums
[rand_idx
]);
int idx
= partition(nums
,l
,r
);
if(idx
==k
) return;
else idx
<k
?quickSelect(nums
,idx
+1,r
,k
):quickSelect(nums
,l
,idx
-1,k
);
}
int partition(vector
<pair
<int,int>>& nums
, int l
, int r
){
auto pivot
= nums
[l
];
while(l
< r
){
while(l
< r
&& nums
[r
].second
> pivot
.second
) --r
; nums
[l
] = nums
[r
];
while(l
< r
&& nums
[l
].second
<= pivot
.second
) ++l
; nums
[r
] = nums
[l
];
}
nums
[l
] = pivot
;
return l
;
}
};
时间复杂度:由于引入了随机化,时间代价的期望是
O
(
n
)
O\left( {n} \right)
O(n)空间复杂度:
O
(
n
)
O\left( {n} \right)
O(n)
3. 桶排序
class Solution {
public:
vector
<int> topKFrequent(vector
<int>& nums
, int k
) {
unordered_map
<int,int> map
;
for(auto num
:nums
)
++map
[num
];
int len
= nums
.size();
vector
<vector
<int>> buckets(len
+1);
for(auto it
:map
)
buckets
[it
.second
].emplace_back(it
.first
);
vector
<int> res
;
for(int i
=len
;i
>=0;--i
){
for(auto it
:buckets
[i
]){
res
.emplace_back(it
);
if(--k
==0) return res
;
}
}
return res
;
}
};
时间复杂度:
O
(
n
)
O\left( {n} \right)
O(n)空间复杂度:
O
(
n
)
O\left( {n} \right)
O(n)