Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述
给你一个整数数组 nums 和一个整数 k,请你返回其中出现频率前 k 高的元素。你可以按任意顺序返回答案。
输入:
nums = [1,1,1,2,2,3], k = 2
输出:
[1,2]
提示:
- 1 <= nums.length <= 10^5
- k 的取值范围是 [1, 数组中不相同的元素的个数]
- 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
二、思路分析
思路一、可以对 nums 数组中的元素进行计数,并将计数结果存入数组,之后对计数数组进行由大到小排序,并找出前 k 个计数结果所对应的元素即可。此思路比较容易实现,但由于可能有O(n)个不同的出现次数,所以复杂度会达到O(nlogn)。
思路二、可以利用小顶堆来进行求解,当得到计数数组后,维护一个小顶堆,遍历计数数组。若堆中元素小于 k 个则直接插入,否则弹出堆顶元素,保证堆中元素不超过 k 个。
本题中使用小顶堆我们需要重写接口
type Interface interface{
sort.Interface
//向堆中添加元素
Push(x interface{})
//弹出堆中元素
Pop() interface{}
}
其中 sort.Interface 包括三个方法
type Interface interface{
//获取堆长度
Len() int
//根据需要对堆进行排序
Less(i, j int) bool
//交换堆中索引为i和j的元素
Swap(i, j int)
}
三、代码
func topKFrequent(nums []int, k int) []int {
temp := make(map[int]int)
for i:=0; i<len(nums); i++{
temp[nums[i]] ++
}
h := &Heap{}
heap.Init(h)
for key, val := range temp{
heap.Push(h, [2]int{key,val})
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 Heap [][2]int
func (h Heap) Len() int{
return len(h)
}
func (h Heap) Less(i,j int) bool {
return h[i][1]<h[j][1]
}
func (h Heap) Swap(i,j int) {
h[i],h[j] = h[j],h[i]
}
func (h *Heap) Push (x interface{}) {
*h = append(*h, x.([2]int))
}
func (h *Heap) Pop() (interface{}) {
old := *h
x := old[len(old)-1]
*h = old[:len(old)-1]
return x
}
四、总结
通过本题学习了如何使用go语言实现小顶堆,并对堆中元素进行操作。并通过小顶堆将算法的时间复杂度降低为 O(logk),算法的空间复杂度降低为 O(n)。