堆的使用 Golang 中没有给出堆的具体实现,仅提供了标准容器库 container/heap
,需手动实现。
heap 接口定义如下
1 2 3 4 5 type Interface interface { sort.Interface Push(x interface {}) Pop() interface {} }
该接口同时继承了 sort.Interface
,定义如下
1 2 3 4 5 6 7 8 9 type Interface interface { Len() int Less(i, j int ) bool Swap(i, j int ) }
故创建堆时需实现 Len()
、Less(i, j int)
、Swap(i, j int)
、Push(x interface{})
、Pop()
五个方法。
向堆中插入节点时,堆会自动调整结构,Golang 中始终保持最后一个元素为堆顶,故 Pop 时返回最后一个节点 并删除即可。
实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package mainimport ( "container/heap" "fmt" "math/rand" "strconv" "time" ) type Person struct { Name string Age int } type PersonHeap []Personfunc (ph PersonHeap) Len() int { return len (ph) } func (ph PersonHeap) Swap(i, j int ) { ph[i], ph[j] = ph[j], ph[i] } func (ph PersonHeap) Less(i, j int ) bool { return ph[i].Age < ph[j].Age } func (ph *PersonHeap) Push(p interface {}) { *ph = append (*ph, p.(Person)) } func (ph *PersonHeap) Pop() interface {} { n := len (*ph) result := (*ph)[n-1 ] *ph = (*ph)[:n-1 ] return result } func main () { rand.Seed(time.Now().Unix()) hp := &PersonHeap{} for i := 0 ; i < 6 ; i++ { *hp = append (*hp, Person{"p" + strconv.Itoa(i), rand.Intn(50 )}) } fmt.Printf("原始切片: %#v\n" , hp) heap.Init(hp) fmt.Printf("堆: %#v\n" , hp) fmt.Println(hp.Pop()) heap.Push(hp, Person{"newP" , 30 }) fmt.Printf("%#v\n" , hp) }
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 package mainimport ( "container/heap" "fmt" ) type ListNode struct { Val int Next *ListNode } type PriorityQueue []*ListNodefunc (pq PriorityQueue) Len() int { return len (pq) } func (pq PriorityQueue) Less(i, j int ) bool { return pq[i].Val < pq[j].Val } func (pq *PriorityQueue) Swap(i, j int ) { (*pq)[i].Val, (*pq)[j].Val = (*pq)[j].Val, (*pq)[i].Val } func (pq *PriorityQueue) Push(x interface {}) { *pq = append (*pq, x.(*ListNode)) } func (pq *PriorityQueue) Pop() interface {} { result := (*pq)[len (*pq)-1 ] *pq = (*pq)[:len (*pq)-1 ] return result } func mergeKLists (lists []*ListNode) *ListNode { if lists == nil || len (lists) == 0 { return nil } dummyHead := &ListNode{0 , nil } curNode := dummyHead var pq PriorityQueue for _, list := range lists { tmp := list for tmp != nil { heap.Push(&pq, tmp) tmp = tmp.Next } } for len (pq) != 0 { curNode.Next = heap.Pop(&pq).(*ListNode) curNode = curNode.Next } curNode.Next = nil return dummyHead.Next } func main () { l1 := &ListNode{1 , nil } l1.Next = &ListNode{4 , nil } l1.Next.Next = &ListNode{5 , nil } l2 := &ListNode{1 , nil } l2.Next = &ListNode{3 , nil } l2.Next.Next = &ListNode{4 , nil } l3 := &ListNode{2 , nil } l3.Next = &ListNode{6 , nil } lists := []*ListNode{l1, l2, l3} result := mergeKLists(lists) for result != nil { fmt.Printf("%d " , result.Val) result = result.Next } }