347. 前 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 是数组大小。


1、使用小根堆,将频率小的数据pop,留下的就是k个频率大的数据。

func topKFrequent(nums []int, k int) []int {
	// 统计nums的数量
	map_num := make(map[int]int)
	for _, num := range nums {
		map_num[num]++
	}
	// 创建小根堆,维护小根堆的元素
	h := &IHeap{}
	heap.Init(h)
	for key, val := range map_num {
		// 插入元素,如果堆中元素个数大于k,则删除堆顶元素
		heap.Push(h, [2]int{key, val})
		if h.Len() > k {
			heap.Pop(h) // 移除频率最小的元素
		}
	}

	// 结果数组
	result := make([]int, k)
	for i := k - 1; i >= 0; i-- { // 反向填充结果,确保频率大的元素在前面
		result[i] = heap.Pop(h).([2]int)[0]
	}
	return result
}

// IHeap 构建小根堆,切片里面存储有两个元素的数组,hash存储的kv
type IHeap [][2]int

func (h IHeap) Len() int {
	return len(h)
}

func (h IHeap) Less(i, j int) bool {
	// 比较value的大小,构建小根堆
	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{}) {
	// 类型断言,断言 x 是 [2]int 类型
	*h = append(*h, x.([2]int))
}

func (h *IHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[:n-1]
	// 返回被移除的元素
	return x
}

以上需要注意的就是,“container/heap” 这个包里面已经给我设计好了接口,我们只需要实现这个接口就可以了。

type Interface interface {
	sort.Interface
	Push(x any) // add x as element Len()
	Pop() any   // remove and return element Len() - 1.
}
type Interface interface {
	Len() int
	Less(i, j int) bool
	Swap(i, j int)
}

在heap中,已经定义好了接口,我们只需要自定义实现这个五个方法,就可以实现我们定义好的功能了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

席万里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值