Top K Frequent Elements

之前写的一个很随意的遍历 k 次取最大值 , 时间复杂度 kn

先排序再取的复杂度 nlogn

用最大堆平均复杂度是 nlogk

kn>>nlogn>nlogk

最大堆 (目前已知最优解)

Leetcode 347. Top K Frequent Elements

复盘:

顺便用 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;


遍历 k 次取值

Leetcode 347. Top K Frequent Elements

复盘:

这里学到了用位运算取得 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
}

你可能感兴趣的:(Top K Frequent Elements)