Open azl397985856 opened 3 years ago
Map + heap
class Solution {
public int[] topKFrequent(int[] nums, int k) {
int[] res = new int[k];
Map<Integer, Integer> map = new HashMap<>();
for (int n: nums) {
map.put(n, map.getOrDefault(n, 0)+1);
}
PriorityQueue<Map.Entry<Integer, Integer>> heap = new PriorityQueue<>((a,b) -> a.getValue() - b.getValue());
for (Map.Entry<Integer,Integer> entry: map.entrySet()) {
heap.offer(entry);
if (heap.size() > k) {
heap.poll();
}
}
for (int i = 0; i < k; i++) {
Map.Entry<Integer, Integer> entry = heap.poll();
res[i] = entry.getKey();
}
return res;
}
}
小顶堆实现队列
代码
import heapq class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: #要统计元素出现频率 map_ = {} #nums[i]:对应出现的次数 for i in range(len(nums)): map_[nums[i]] = map_.get(nums[i], 0) + 1
#对频率排序
#定义一个小顶堆,大小为k
pri_que = [] #小顶堆
#用固定大小为k的小顶堆,扫面所有频率的数值
for key, freq in map_.items():
heapq.heappush(pri_que, (freq, key))
if len(pri_que) > k: #如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
heapq.heappop(pri_que)
#找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒叙来输出到数组
result = [0] * k
for i in range(k-1, -1, -1):
result[i] = heapq.heappop(pri_que)[1]
return result
## 复杂度
时间:O(nlogk)
空间:O(n)
topK问题, 容易想到使用优先队列(堆排序)。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> res;
unordered_map<int, int> dict; // 映射: value -> count
for (auto num : nums)
{
if (dict.find(num) == dict.end()) dict[num] = 0;
else dict[num]++;
}
auto cmp = [](pair<int, int> p1, pair<int, int> p2)
{
return p1.second < p2.second; /* 大顶堆 */
};
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> q(cmp);
for (auto kvp : dict) q.push(kvp);
while (k > 0)
{
res.push_back(q.top().first);
q.pop();
k--;
}
return res;
}
};
python
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
counter = collections.Counter(nums)
buckets = [[] for _ in range(n)]
for key in counter:
buckets[counter[key]-1].append(key)
res=[]
for i in range(n - 1, -1, -1):
for b in buckets[i]:
res.append(b)
if len(res) >= k:
return res
return res
暴力解哈希表+排序,时间复杂度为nlogn,采用堆之后达到进阶要求。
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
from collections import defaultdict
import heapq
d=defaultdict(int)
for i in nums:
d[i]+=1
kv=list(d.items())
res=[]
for i in range(k):
heapq.heappush(res,[kv[i][1],kv[i][0]])
for j in range(k,len(kv)):
k,v=kv[j]
if v>res[0][0]:
heapq.heappop(res)
heapq.heappush(res,[kv[j][1],kv[j][0]])
final=[i[1] for i in res]
return final
时间复杂度:O(nlogk),堆排序
空间复杂度:O(n),哈希表长度
暴力解法。
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
from collections import defaultdict
d=defaultdict(int)
for i in nums:
d[i]+=1
r=sorted(d.items(),key=lambda x:-x[1])
res=[]
for i in range(k):
res.append(r[i][0])
return res
哈希表+排序
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
dic = Counter(nums)
return sorted(dic.keys(),key = lambda x:-dic[x])[:k]
只想到了用哈希表然后排序的方法,之后学习一下堆排的写法
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
d = {}
for num in nums:
if num not in d:
d[num] = 1
else:
d[num] += 1
t: List[Tuple] = sorted(d.items(), key=lambda x: x[1], reverse=True)
return [i[0] for i in t[:k]]
使用hashmap存frequency,O(N).
然后利用heap得到topk的element,O(KLOGN)
import collections, heapq as hp
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
my_list = collections.defaultdict(int)
for num in nums:
my_list[num] += 1
result = []
b = []
for key in my_list:
b.append((-my_list[key],key))
hp.heapify(b)
result = []
for i in range(k):
result.append(hp.heappop(b)[1])
return result
复杂度分析
用dict记录每一个数的频率,然后排序
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
import collections
count_dict = collections.defaultdict(int)
for i in nums:
count_dict[i] += 1
sorted_dict = sorted(count_dict.items(), key = lambda x:x[1],reverse = True)
result = []
for i in range(k):
result.append(sorted_dict[i][0])
return result
时间复杂度 :O(N*logN)
空间复杂度:O(N)
哈希表 unordered_map + 最小堆 priority_queue 的方法(C++)
class Solution {
public:
// 小顶堆
class mycomparison {
public:
bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
return lhs.second > rhs.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> map;
// 创建 map,map的键是数组元素,键值是数组元素出现次数
for(auto num: nums){
map[num]++;
}
// 定义一个小顶堆,并维持大小为 k
priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison > heap; // 小顶堆,堆顶为最小值
for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
heap.push(*it);
if(heap.size() > k) heap.pop(); // 弹出堆顶元素,即最小元素
}
// heap 元素倒序输出到数组
vector<int> ret(k);
for (int i=k-1; i>=0; i--){
ret[i] = heap.top().first;
heap.pop();
}
return ret;
}
};
priority queue + hashmap
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
if k == len(nums):
return nums
count = {}
for item in nums:
if item not in count:
count[item] = (0, item)
count[item] = (count[item][0] + 1, item)
heap = []
for value in count.values():
heapq.heappush(heap, value)
if len(heap) > k:
heapq.heappop(heap)
ans = []
for i in range(k):
ans.append(heapq.heappop(heap)[1])
return ans
T: O(nlogk) S: O(n + k)
The power of Counter. Time: O(nlgk) because most_common use a heap of size k to find the most frequent k items. Space: O(n)
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
return [x[0] for x in Counter(nums).most_common(k)]
先拿到nums里面每个num的count
然后把他放到最大queue里面
然后pop k次 放进results
import heapq
from collections import Counter
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
"""
heap solution
"""
num_count_dict = Counter(nums)
num_count_heap = [(-count, num) for num, count in num_count_dict.items()]
heapq.heapify(num_count_heap)
result = []
for _ in range(k):
result.append(heapq.heappop(num_count_heap)[1])
return result
time O(klgn)
space O(n)
Heap + Counter
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
Counter = collections.Counter(nums) #O(N)
if len(Counter)<=k:
return Counter.keys()
heap=[]
for key,value in Counter.items(): #O(NlogK)
heapq.heappush(heap,(value,key))
if len(heap)>k:
heapq.heappop(heap)
return [key for value,key in heap]
时间复杂度:O(NlogK) 空间复杂度: O(N+K)
Explanation
Python
# Approach 1
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
result = []
d = defaultdict(int)
for n in nums:
d[n] += 1
for i in sorted(d.items(), key=lambda item: item[1], reverse=True):
if k == 0:
return result
result.append(i[0])
k -= 1
return result
# Approach 2
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
if k == len(nums):
return nums
count = Counter(nums)
return heapq.nlargest(k, count.keys(), key=count.get)
Complexity
Approach 1:
O(N)
O(N)
Approach 2:
O(Nlogk)
if k < N and O(N)
if k = NO(N + k)
哈希表计数,根据计数大小,对哈希表的keySet(所有不同数字)排序后输出前k个元素
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function(nums, k) {
const counters = new Map();
nums.forEach(num => {
if (counters.has(num)) {
counters.set(num, counters.get(num) + 1);
} else {
counters.set(num, 1);
}
});
return [...counters.keys()].sort((n1, n2) => {
return counters.get(n2) - counters.get(n1);
}).slice(0, k);
};
AC
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Arrays.sort(nums);
int count = 1;
PriorityQueue<int[]> heap = new PriorityQueue<>((o1, o2)->o2[1] - o1[1]);
for(int i = 0;i < nums.length;i++){
if(i < nums.length - 1 && nums[i] == nums[i+1]){
count++;
} else {
heap.add(new int[]{nums[i], count});
count = 1;
}
}
int[] res = new int[k];
for(int i = 0;i < k;i++){
res[i] = heap.poll()[0];
}
return res;
}
}
time: 排序,O(NlogN),遍历一次求count,O(N),弹出topK,O(KlogD), D是不同的元素的个数,最坏为O(KlogN);总的复杂度取最高O(NlogN); space:heap所需的空间O(D), D是不同的元素的个数,最坏为O(N)
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
dic = {}
for i in nums:
dic[i] = dic.get(i, 0) + 1
tmp = {}
for key, v in dic.items():
tmp.setdefault(v, []).append(key)
res = []
for i in range(k):
res += tmp.pop(max(tmp))
if len(res) == k:
return res
use maxheap to maintain the order of frequency
class Solution(object):
def topKFrequent(self, nums, k):
dic = Counter(nums)
maxheap = []
heapq.heapify(maxheap)
for key in dic.keys():
heapq.heappush(maxheap, [-dic[key], key])
result = []
while k > 0 and maxheap:
getOne = heapq.heappop(maxheap)
result.append(getOne[1])
k -= 1
return result
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
buckets = [[] for _ in range(len(nums) + 1)]
d = {}
for num in nums:
d[num] = d.get(num, 0) + 1
for num, freq in d.items():
buckets[freq].append(num)
res = []
for i in range(len(buckets)-1, -1, -1):
bucket = buckets[i]
if bucket:
for num in bucket:
res.append(num)
return res[:k]
Quick Select
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> counterMap = new HashMap<>();
for (int n : nums){
counterMap.put(n, counterMap.getOrDefault(n, 0) + 1);
}
int[] array = new int[counterMap.size()];
int index = 0;
for (int n : counterMap.keySet()){
array[index++] = n;
}
quickSelect(array, 0, array.length - 1, counterMap, k);
return Arrays.copyOfRange(array, array.length - k, array.length);
}
private void quickSelect(int[] array, int left, int right, Map<Integer, Integer> map, int k){
int pivot = map.get(array[right]), index = left;
for (int i = left; i < right; i++){
if (map.get(array[i]) <= pivot){
swap(array, i, index++);
}
}
swap(array, index, right);
int count = right - index + 1;
if (count == k) return;
else if (count > k) quickSelect(array, index + 1, right, map, k);
else quickSelect(array, left, index - 1, map, k - count);
}
private void swap(int[] nums, int i, int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
Time Complexity: Best Case: O(N), Worst Case: O(N^2) Space Complexity: O(N)
Java code
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> countMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
countMap.put(nums[i], countMap.getOrDefault(nums[i], 0) + 1);
}
PriorityQueue<Map.Entry<Integer, Integer>> priorityQueue = new PriorityQueue<>(Comparator.comparingInt(Map.Entry::getValue));
for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
priorityQueue.add(entry);
if (priorityQueue.size() > k) {
priorityQueue.poll();
}
}
List<Integer> resList = new ArrayList<>();
while (!priorityQueue.isEmpty()) {
resList.add(priorityQueue.poll().getKey());
}
int[] res = new int[resList.size()];
for (int i = 0; i < res.length; i++) {
res[i] = resList.get(i);
}
return res;
}
思路:
复杂度分析: 方法一、 时间复杂度: O(nlogn), n为数组nums的元素个数 空间复杂度: O(n + k)
方法二 时间复杂度: O(nlogk), n为数组nums的元素个数 空间复杂度: O(n + k)
代码(C++):
//方法二:
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int, int> freq;
// use a hashmap to store the frequency of each element
for (auto n : nums) // O(n)
freq[n]++;
// use min heap to store the k most frequent elements
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
for (auto f : freq) { // o(nlogk)
if (pq.size() < k)
pq.push({f.second, f.first}); // stack sort o(logk)
else if (pq.top().first < f.second) {
pq.pop();
pq.push({f.second, f.first});
}
}
vector<int> res;
while (!pq.empty()) { // O(k)
res.push_back(pq.top().second);
pq.pop();
}
return res;
}
};
Algo
- hashmap, key->number, val->frequency
- Heap sort
- heap to arr
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
# corner case
if k == len(nums): return nums
# collections.Counter is a hashmap that key->number, val->frequence
count = collections.Counter(nums)
# heapq.nlargest(k, count.keys(), key=count.get)
# means "find k largest" + "from count.keys()" + "by count.get(akey)"
return heapq.nlargest(k, count.keys(), key=count.get)
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = collections.Counter(nums)
return [item[0] for item in count.most_common(k)]
https://leetcode.com/problems/top-k-frequent-elements/
const topKFrequent = (nums, k) => {
const map = {};
const result = [];
const bucket = Array(nums.length + 1)
.fill()
.map(() => []);
for (let num of nums) {
map[num] = ~~map[num] + 1;
}
for (let num in map) {
bucket[map[num]].push(parseInt(num));
}
for (let i = nums.length; i >= 0 && k > 0; k--) {
while (bucket[i].length === 0) i--;
result.push(bucket[i].shift());
}
return result;
};
空间时间均为O(n)
idea: use a hashmap to record the frequency of each number. Then construct a min-Heap with size of k. The min-heap hold the entryset of the map. When it's size is larger than k, poll the top of the heap. In the end, output the whole heap. Time: O(NlogK) Space: O(n)
class Solution {
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> counter = new HashMap<>();
for(int num: nums)
counter.put(num,counter.getOrDefault(num,0)+1);
PriorityQueue<Map.Entry<Integer,Integer>> pq = new PriorityQueue<>((a,b)->a.getValue()-b.getValue());
for(Map.Entry<Integer, Integer> entry: counter.entrySet()) {
pq.offer(entry);
if(pq.size()>k)
pq.poll();
}
int[] res = new int[k];
int i=0;
while(!pq.isEmpty()) {
res[i++]=pq.poll().getKey();
}
return res;
}
}
https://leetcode-cn.com/problems/top-k-frequent-elements/
HashMap记录数字的频率,使用一个size为K的最小堆来记录,堆顶元素为前k个高频中频率最低的那个,当新的数字来时只需要对比两个的频率即可。
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for(int num : nums) {
if(map.containsKey(num)) {
map.put(num, map.get(num) + 1);
} else {
map.put(num, 1);
}
}
Queue<Integer> queue = new PriorityQueue<>((a, b) -> map.get(a) - map.get(b));
for(Integer num : map.keySet()) {
if(queue.size() < k) {
queue.offer(num);
} else if(map.get(num) > map.get(queue.peek())) {
queue.poll();
queue.offer(num);
}
}
int[] res = new int[k];
for(int i = 0; i < k; i++) {
res[i] = queue.poll();
}
return res;
}
}
O(n) + O (nlogk)
O(n + k)
重点题,bucket 和 quickSelect都要练习一下
fun topKFrequent(nums: IntArray, k: Int): IntArray {
val map = nums.asSequence().groupingBy { it }.eachCount()
val bucket = Array<MutableList<Int>?>(nums.size + 1) { null }
map.forEach {
bucket[it.value] = bucket[it.value]?.apply {
add(it.key)
} ?: mutableListOf(it.key)
}
val res = mutableListOf<Int>()
for (freq in bucket.lastIndex downTo 1) {
bucket[freq]?.apply {
res.addAll(take(minOf(k - res.size, size)))
}
if (res.size == k) return res.toIntArray()
}
return res.toIntArray()
}
思路: 用hashmap记录数字的频率,然后将hashmap里的元素排序,然后返回前k个。 Python 3 Code:
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
hashmap = defaultdict(int)
for num in nums:
hashmap[num] += 1
ans = []
freqs = sorted(hashmap.items(), key = lambda x:x[1])
while k > 0:
num, freq = freqs.pop()
ans.append(num)
k -= 1
return ans
Time Complexity: O(N*log(N) Space Complexity: O(N)
LC 347. Top K Frequent Elements
Ideas
comment Runtime: 40 ms beat 75%
python代码
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
hashmap = dict()
for num in nums:
hashmap[num] = 0
for num in nums:
if num in hashmap:
hashmap[num] +=1
sort_map = dict(sorted(hashmap.items(), key = lambda item:item[1],reverse=True))
i = 0
result = []
for num, count in enumerate(sort_map):
if i < k:
result.append(count)
i = i+1
else:
break
return result
复杂度分析
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
freq = {}
for num in nums:
freq[num] = freq.get(num,0) + 1
heap = []
for num, count in freq.items():
heapq.heappush(heap,(count,num))
if len(heap) > k:
heapq.heappop(heap)
return [pairs[1] for pairs in heap ]
# Time: O(nlogk) / Space: O(n + k)
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map =new HashMap<>();
int len = nums.length;
int maxCount=1;
for(int i=0;i<len;i++){
int count = map.getOrDefault(nums[i],0)+1;
if(count>maxCount){
maxCount = count;
}
map.put(nums[i],count);
}
List<List<Integer>> list = new ArrayList<>(maxCount+1);
for(int i=0;i<maxCount+1;i++){
List<Integer> l = new ArrayList<>();
list.add(l);
}
//遍历map,放到list中
for(Integer key:map.keySet()){
Integer count = map.get(key);
List<Integer> mid = list.get(count);
mid.add(key);
}
//从数组的后面开始遍历取k个
int[] res = new int[k];
int index=0;
for(int i=maxCount;i>=0;i--){
if(index>=k){
break;
}
List<Integer> items = list.get(i);
if(!items.isEmpty()){//说明有值
for(Integer item:items){
res[index++]=item;
}
}
}
return res;
}
}
复杂度分析
令 n 为数组长度。
Hash table and bucket sort
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
memo = collections.defaultdict(lambda:0)
bucket = [[] for _ in range(len(nums)+1)]
res = []
for num in nums:
memo[num] += 1
for key in memo:
bucket[memo[key]].append(key)
for i in range(len(bucket)-1, 0, -1):
if k <=0: break
if bucket[i]:
res+=bucket[i]
k -= len(bucket[i])
return res
Space: O(N) Time: O(N)
HashMap。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> hashMap;
vector<pair<int, int>> count;
vector<int> res;
for (int i = 0; i < nums.size(); i++) {
if (hashMap.count(nums[i])) {
hashMap[nums[i]]++;
} else {
hashMap[nums[i]] = 1;
}
}
for (auto &i : hashMap) count.push_back({i.second, i.first});
sort(count.rbegin(), count.rend());
for (int i = 0; i < k; i++) res.push_back(count[i].second);
return res;
}
};
# use hashmap: key(num), value(-count)
# use priority queue to get top K frequent number
# time: O(NlogN), N is the number of unique elements in nums
# space: O(N)
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
if not nums or not k:
return []
counter = {}
for n in nums:
counter[n] = counter.get(n, 0) - 1
heap = []
# push a pair into heap, sort by first element by default
for key in counter:
heapq.heappush(heap, (counter[key], key))
res = []
while k > 0 and heap:
res.append(heapq.heappop(heap)[1])
k -= 1
return res
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 先用map记住每一个元素出现的次数
Map<Integer, Integer> count = new HashMap<>();
for (int num : nums) {
count.put(num, count.getOrDefault(num, 0) + 1);
}
// 自定义比较器,按出现次数升序排列
PriorityQueue<Integer> pq = new PriorityQueue<>(k + 1, (a, b)->count.get(a) - count.get(b));
// 填充队列
for(int num : count.keySet()) {
pq.add(num);
if (pq.size() > k) pq.remove();
}
// 转换为数组并返回
int[] ans = new int[k];
int index = 0;
while (!pq.isEmpty()) {
ans[index ++] = pq.remove();
}
return ans;
}
}
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
if k == len(nums):
return nums
count = collections.Counter(nums)
return heapq.nlargest(k, count.keys(), key=count.get)
347. 前 K 个高频元素
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/top-k-frequent-elements/
前置知识
- 哈希表
- 堆排序
- 快速选择
题目描述
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。 示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums = [1], k = 1 输出: [1] 提示: - 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。 - 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。 - 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。 - 你可以按任意顺序返回答案。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/top-k-frequent-elements 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
dict1={}
for num1 in nums:
if num1 not in dict1:
dict1[num1]=1
else:
dict1[num1]+=1
dict1_items=sorted(dict1.items(),key=lambda x:x[1],reverse=True)
allRes=[]
for i in range(k):
allRes.append(dict1_items[i][0])
return allRes
时间复杂度:O(N) 空间复杂度:O(N)
用HashMap存频率,用PriorityQueue取出频率最高的k个元素
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int i : nums) {
map.put(i, map.containsKey(i) ? map.get(i) + 1 : 1);
}
int[] result = new int[k];
PriorityQueue<Integer> pq = new PriorityQueue<>( (a, b) -> map.get(b) - map.get(a));
for (int i : map.keySet()) {
pq.add(i);
}
for (int i = 0; i < k; i++) {
result[i] = pq.poll();
}
return result;
}
}
时间复杂度: O(nlogn) 空间复杂度: O(n)
官方解题思路
JavaScript Code
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function (nums, k) {
const counts = {};
for (let num of nums) {
counts[num] = (counts[num] || 0) + 1;
}
let pairs = Object.keys(counts).map((key) => [counts[key], key]);
select(0, pairs.length - 1, k);
return pairs.slice(0, k).map((item) => item[1]);
// 快速选择
function select(left, right, offset) {
if (left >= right) {
return;
}
const pivotIndex = partition(left, right);
console.log({ pairs, pivotIndex });
if (pivotIndex === offset) {
return;
}
if (pivotIndex <= offset) {
select(pivotIndex + 1, right, offset);
} else {
select(left, pivotIndex - 1);
}
}
// 拆分数组为两个part
function partition(left, right) {
const [pivot] = pairs[right];
let cur = left;
let leftPartIndex = left;
while (cur < right) {
if (pairs[cur][0] > pivot) {
swap(leftPartIndex++, cur);
}
cur++;
}
swap(right, leftPartIndex);
return leftPartIndex;
}
function swap(x, y) {
const term = pairs[x];
pairs[x] = pairs[y];
pairs[y] = term;
}
};
复杂度
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
counter = collections.Counter(nums)
sorted_nums = sorted(counter.items(), key = lambda x: -x[1])
result = [key for key, val in sorted_nums]
return result[:k]
哈希表+自定义排序
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int>m;
for(auto x:nums)
m[x]++;
vector<pair<int,int>>v;
for(pair<int,int> x:m)
v.push_back(x);
sort(v.begin(),v.end(),cmp);
vector<int>res;
for(int i=0;i<k;i++)
res.push_back(v[i].first);
return res;
}
static bool cmp(pair<int,int>a,pair<int,int>b)
{
return a.second>b.second;
}
};
复杂度分析
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
return new ArrayList<>(map.keySet()).stream().sorted((o1, o2) -> map.get(o2) - map.get(o1)).limit(k).mapToInt(Integer::intValue).toArray();
}
}
class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
// 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
HashMap<Integer,Integer> map = new HashMap();
for(int num : nums){
if (map.containsKey(num)) {
map.put(num, map.get(num) + 1);
} else {
map.put(num, 1);
}
}
// 遍历map,用最小堆保存频率最大的k个元素
PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return map.get(a) - map.get(b);
}
});
for (Integer key : map.keySet()) {
if (pq.size() < k) {
pq.add(key);
} else if (map.get(key) > map.get(pq.peek())) {
pq.remove();
pq.add(key);
}
}
// 取出最小堆中的元素
List<Integer> res = new ArrayList<>();
while (!pq.isEmpty()) {
res.add(pq.remove());
}
return res;
}
}
时间复杂度:O(nlogn)
空间复杂度:O(n)
先统计出每个元素的出现次数。
借助桶排序的思想从后往前遍历找出出现次数大于K的元素的最小出现频率。那原数组中
出现频率大于该最小频率的元素就是出现频率最高的K个元素。
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> h_cnt;
for(auto& cur:nums){
h_cnt[cur]++;
}
vector<int> cnt_arr(nums.size() + 1, 0);
for(auto [cur, cnt]: h_cnt){
cnt_arr[cnt] ++;
}
int ans_res = 0;
int target_cnt, ii;
for(target_cnt = nums.size(); target_cnt >=0; -- target_cnt){
ans_res += cnt_arr[target_cnt];
if(ans_res >= k){
break;
}
}
vector<int> ans;
for(auto [cur, cnt]: h_cnt){
if(cnt >= target_cnt){
ans.push_back(cur);
if(ans.size() == k) break;
}
}
return ans;
}
};
n 为数组元素个数。
思路
建立哈希表,保存下每个数字出现的次数
对哈希值列表进行排序
关键点˜
代码
Java Code:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,int[]> map = new HashMap<>();
for(int num : nums){
int[] count = map.get(num);
if(count == null){
map.put(num,new int[]{num,1});
}else{
count[1]+=1;
}
}
List<int[]> countList = new ArrayList<>(map.values());
Collections.sort(countList,new Comparator<int[]>(){
@Override
public int compare(int[] o1, int[] o2) {
return o2[1]-o1[1];
}
});
int[] ans = new int[k];
for(int i=0;i<k;i++){
ans[i]=countList.get(i)[0];
}
return ans;
}
}
复杂度分析
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
c = Counter(nums)
# freqs = c.items()
# sorted(freqs, key=lambda x:-x[1])
return [x[0] for x in c.most_common(k)]
const topKFrequent = (nums, k) => {
let map = new Map()
for (let i = 0; i < nums.length; i++) {
if (map.has(nums[i])) {
map.set(nums[i], map.get(nums[i]) + 1)
}
else {
map.set(nums[i], 1)
}
}
let res = [...map]
res.sort((a, b) => b[1] - a[1])
return res.map((n) => n[0]).slice(0, k)
};
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
def sift_down(arr, root, k):
val = arr[root]
while root<<1 < k:
child = root << 1
if child|1 < k and arr[child|1][1] < arr[child][1]:
child |= 1
if arr[child][1] < val[1]:
arr[root] = arr[child]
root = child
else:
break
arr[root] = val
def sift_up(arr, child):
val = arr[child]
while child>>1 > 0 and val[1] < arr[child>>1][1]:
arr[child] = arr[child>>1]
child >>= 1
arr[child] = val
stat = collections.Counter(nums)
stat = list(stat.items())
heap = [(0,0)]
for i in range(k):
heap.append(stat[i])
sift_up(heap, len(heap)-1)
for i in range(k, len(stat)):
if stat[i][1] > heap[1][1]:
heap[1] = stat[i]
sift_down(heap, 1, k+1)
return [item[0] for item in heap[1:]]
347. 前 K 个高频元素
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/top-k-frequent-elements/
前置知识
题目描述
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/top-k-frequent-elements 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。