描述
给定一个非空的整数数组,返回其中出现频率前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是数组的大小。
思路
1. 遍历数组 map记录数字出现的次数
2. 利用长度k的最小堆排序,root节点始终存放的为出现次数最小的数字
3. 遍历map 与堆root比较,如果大于root出现的次数,则将新的数字替换掉root 再次排序
4. 遍历完成后堆里保存的即为结果
实现
type element struct{
Num int
Times int
}
func topKFrequent(nums []int, k int) []int {
numTimeMap := make(map[int]int, 0)
for _, num := range nums{
numTimeMap[num]++
}
heap := make([]element, 0)
ret := make([]int, 0)
sortFlag := false
for num, times := range numTimeMap{
e := element{Num:num, Times:times}
if len(heap) < k{
heap = append(heap, e)
continue
}else if !sortFlag{
topKBuildHeap(heap)
sortFlag = true
}
if e.Times > heap[0].Times{
heap[0] = e
topKHeapSortBody(heap, k, 0)
}
}
for _, e := range heap{
ret = append(ret, e.Num)
}
return ret
}
func topKBuildHeap(elementList []element){
size := len(elementList)
for i := size; i >= 0; i--{
topKHeapSortBody(elementList, size, i)
}
return
}
func topKHeapSortBody(elementList []element, size, curRoot int){
left := 2*curRoot+1
right := 2*curRoot+2
smallest := curRoot
if left < size && elementList[smallest].Times > elementList[left].Times {
smallest = left
}
if right < size && elementList[smallest].Times > elementList[right].Times {
smallest = right
}
if smallest != curRoot{
elementList[smallest], elementList[curRoot] = elementList[curRoot], elementList[smallest]
topKHeapSortBody(elementList, size, smallest)
}
return
}