之前寫的一個很隨意的遍歷 k 次取最大值 , 時間複雜度 kn
先排序再取的複雜度 nlogn
用最大堆平均複雜度是 nlogk
kn>>nlogn>nlogk
覆盤:
順便用 LeetCode 這題的 Testcase 測出了之前寫的最大堆shiftDown 的 bug , 呼 , shiftDown 的邏輯確實有點亂 , 容易出 bug
找個時間寫個通用的最大堆,像 C++裡泛型那樣的寫法, 然後實現 Compareable 介面
偽碼:
//maxheap solution , 還有優化空間複雜度的餘地,以後再寫
topKFre(nums,k) {
make a map[int]=freq
iterate nums
map[num]++
iterate map
insert [num,freq] into maxheap
res=[]
iterate k times
res=maxHeap.extractMax()[0]
return res
}
struct pair{
num
freq
compareTo()
}
func topKFrequent(nums []int, k int) []int {
m:=make(map[int]int)
h:=Constructor()
for _,v:=range nums {
m[v]++
}
for k,v:=range m {
h.add([]int{k,v})
}
res:=[]int{}
for i:=1;i<=k;i++ {
res=append(res,h.extractMax()[0])
}
return res
}
type MaxHeap struct {
data [][]int
size int
}
func Constructor() *MaxHeap{
return &MaxHeap{}
}
func (t *MaxHeap) sizes() int{
return t.size
}
func (t *MaxHeap) isEmpty() bool{
return t.size==0
}
func (t *MaxHeap) parent(index int) int{
if index==0 {
panic("index 0 dont have parent")
}
return (index-1)/2
}
func (t *MaxHeap) leftChild(index int) int{
return 2*index+1
}
func (t *MaxHeap) rightChild(index int) int{
return 2*index+2
}
func (t *MaxHeap) add(v []int) {
t.data=append(t.data,v)
t.size++
newValueIndex := t.size-1
if newValueIndex!=0 {
t.shiftUp(newValueIndex)
}
}
func (t *MaxHeap) shiftUp(index int) {
parent:=t.parent(index)
for parent>=0 && t.data[index][1]>t.data[parent][1] {
tmp:=t.data[index]
t.data[index]=t.data[parent]
t.data[parent]=tmp
index=parent
if parent==0 {
break
}
parent= t.parent(index)
}
}
func (t *MaxHeap) extractMax() []int{
max:=t.data[0]
t.data[0]=t.data[t.size-1]
t.size--
t.data=t.data[:t.size] //移除最後一個元素,其實也可以不用刪吧
t.shiftDown(0)
return max
}
func (t *MaxHeap) shiftDown(index int) {
for t.leftChild(index)<=t.size-1 || t.rightChild(index)<=t.size-1 { //bug 在這
leftIndex:=t.leftChild(index)
rightIndex:=t.rightChild(index)
var bV []int
var bI int
if t.rightChild(index)>t.size-1 { //bug 在這
bV=t.data[leftIndex]
bI=leftIndex
} else if t.data[leftIndex][1]>t.data[rightIndex][1] { //bug 在這 , rightIndex 可能沒值了
bV=t.data[leftIndex]
bI=leftIndex
} else {
bV=t.data[rightIndex]
bI=rightIndex
}
if t.data[index][1]>bV[1] {
break
}
tmp:=t.data[index]
t.data[index]=bV
t.data[bI]=tmp
index=bI
}
}
覆盤:
這題也要找個時間寫個通用的泛型排序
//TODO;
覆盤:
這裡學到了用位運算取得 INT 最大值最小值的方法
package main
const INT_MAX = int(^uint(0) >> 1)
const INT_MIN = ^INT_MAX
func topKFrequent(nums []int, k int) []int {
m:=make(map[int]int)
for _,v:=range nums {
m[v]++
}
res:=[]int{}
for i:=1;i<=k;i++{
maxK:=INT_MIN
indexK:=INT_MIN
for k,v:=range m {
if v> maxK {
maxK=v
indexK=k
}
}
res=append(res,indexK)
delete(m,indexK)
}
return res
}