class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
}
};
347. 前 K 个高频元素
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
1 <= nums.length <= 105
k
的取值范围是 [1, 数组中不相同的元素的个数]
k
个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n)
,其中 n
是数组大小。
原站题解
rust 解法, 执行用时: 3 ms, 内存消耗: 2.3 MB, 提交时间: 2024-05-28 00:34:31
use std::{ cmp::Reverse, collections::{BinaryHeap, HashMap}, }; impl Solution { pub fn top_k_frequent(nums: Vec<i32>, k: i32) -> Vec<i32> { let mut map = HashMap::new(); nums.into_iter().for_each(|x| { map.entry(x).and_modify(|x| *x += 1).or_insert(1); }); let mut heap = BinaryHeap::with_capacity(k as usize + 1); map.iter().take(k as usize).for_each(|x| { heap.push((Reverse(x.1), x.0)); }); map.iter().skip(k as usize).for_each(|x| { heap.push((Reverse(x.1), x.0)); heap.pop(); }); heap.into_sorted_vec().into_iter().map(|x| *x.1).collect() } }
java 解法, 执行用时: 11 ms, 内存消耗: 47.6 MB, 提交时间: 2024-05-28 00:33:42
class Solution { public int[] topKFrequent(int[] nums, int k) { // 统计每个数字出现的次数 Map<Integer, Integer> counterMap = IntStream.of(nums).boxed().collect(Collectors.toMap(e -> e, e -> 1, Integer::sum)); // 定义二叉搜索树:key 是数字出现的次数,value 是出现了key次的数字列表。 TreeMap<Integer, List<Integer>> treeMap = new TreeMap<>(); // 维护一个有 k 个数字的二叉搜索树: // 不足 k 个直接将当前数字加入到树中;否则判断当前树中的最小次数是否小于当前数字的出现次数,若是,则删掉树中出现次数最少的一个数字,将当前数字加入树中。 int count = 0; for(Map.Entry<Integer, Integer> entry: counterMap.entrySet()) { int num = entry.getKey(); int cnt = entry.getValue(); if (count < k) { treeMap.computeIfAbsent(cnt, ArrayList::new).add(num); count++; } else { Map.Entry<Integer, List<Integer>> firstEntry = treeMap.firstEntry(); if (cnt > firstEntry.getKey()) { treeMap.computeIfAbsent(cnt, ArrayList::new).add(num); List<Integer> list = firstEntry.getValue(); if (list.size() == 1) { treeMap.pollFirstEntry(); } else { list.remove(list.size() - 1); } } } } // 构造返回结果 int[] res = new int[k]; int idx = 0; for (List<Integer> list: treeMap.values()) { for (int num: list) { res[idx++] = num; } } return res; } }
java 解法, 执行用时: 12 ms, 内存消耗: 47.9 MB, 提交时间: 2024-05-28 00:33:27
class Solution { public int[] topKFrequent(int[] nums, int k) { // 统计每个数字出现的次数 Map<Integer, Integer> counter = IntStream.of(nums).boxed().collect(Collectors.toMap(e -> e, e -> 1, Integer::sum)); // 定义小根堆,根据数字频率自小到大排序 Queue<Integer> pq = new PriorityQueue<>((v1, v2) -> counter.get(v1) - counter.get(v2)); // 遍历数组,维护一个大小为 k 的小根堆: // 不足 k 个直接将当前数字加入到堆中;否则判断堆中的最小次数是否小于当前数字的出现次数,若是,则删掉堆中出现次数最少的一个数字,将当前数字加入堆中。 counter.forEach((num, cnt) -> { if (pq.size() < k) { pq.offer(num); } else if (counter.get(pq.peek()) < cnt) { pq.poll(); pq.offer(num); } }); // 构造返回结果 int[] res = new int[k]; int idx = 0; for (int num: pq) { res[idx++] = num; } return res; } }
golang 解法, 执行用时: 5 ms, 内存消耗: 5.7 MB, 提交时间: 2024-05-28 00:32:32
//方法一:小顶堆 func topKFrequent(nums []int, k int) []int { map_num:=map[int]int{} //记录每个元素出现的次数 for _,item:=range nums{ map_num[item]++ } h:=&IHeap{} heap.Init(h) //所有元素入堆,堆的长度为k for key,value:=range map_num{ heap.Push(h,[2]int{key,value}) if h.Len()>k{ heap.Pop(h) } } res:=make([]int,k) //按顺序返回堆中的元素 for i:=0;i<k;i++{ res[k-i-1]=heap.Pop(h).([2]int)[0] } return res } //构建小顶堆 type IHeap [][2]int func (h IHeap) Len()int { return len(h) } func (h IHeap) Less (i,j int) bool { return h[i][1]<h[j][1] } func (h IHeap) Swap(i,j int) { h[i],h[j]=h[j],h[i] } func (h *IHeap) Push(x interface{}){ *h=append(*h,x.([2]int)) } func (h *IHeap) Pop() interface{}{ old:=*h n:=len(old) x:=old[n-1] *h=old[0:n-1] return x } //方法二:利用O(logn)排序 func topKFrequent2(nums []int, k int) []int { ans:=[]int{} map_num:=map[int]int{} for _,item:=range nums { map_num[item]++ } for key,_:=range map_num{ ans=append(ans,key) } //核心思想:排序 //可以不用包函数,自己实现快排 sort.Slice(ans,func (a,b int)bool{ return map_num[ans[a]]>map_num[ans[b]] }) return ans[:k] }
python3 解法, 执行用时: 44 ms, 内存消耗: 17.7 MB, 提交时间: 2022-07-22 10:11:04
class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: c = Counter(nums) res = sorted(c, key=lambda num:-c[num]) return res[:k]