Leetcode 347. Top K Frequent Elements

twisted-fate發表於2019-06-04

之前寫的一個很隨意的遍歷 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;

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
}

相關文章