一、题目
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
二、思路一
分治法两两合并
- 将k个链表配对并将同一对中的链表合并
- 第一轮合并后,k个链表被合并成了$\frac{k}{2}$ 个链表,平均长度为$\frac{2n}{k}$,总共n个元素。然后是$\frac{k}{4}$个链表,$\frac{k}{8}$个链表等等
- 重复这个过程,直到不能再合并
代码实现
>folded main.go1 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
| func mergeKLists(lists []*ListNode) *ListNode { if len(lists) == 0 { return nil }
return merge(lists) }
func merge(lists []*ListNode) *ListNode { llen := len(lists) mid := llen / 2
if llen == 1 { return lists[0] }
if llen == 2 { l1, l2 := lists[0], lists[1] res, cur := &ListNode{}, &ListNode{}
if l1 == nil { return l2 }
if l2 == nil { return l1 }
if l1.Val < l2.Val { res = l1 cur.Next = l1 l1 = l1.Next } else { res = l2 cur.Next = l2 l2 = l2.Next } cur = cur.Next for l1 != nil && l2 != nil { if l1.Val < l2.Val { cur.Next = l1 l1 = l1.Next } else { cur.Next = l2 l2 = l2.Next } cur = cur.Next }
if l1 != nil { cur.Next = l1 }
if l2 != nil { cur.Next = l2 }
return res }
return mergeKLists([]*ListNode{mergeKLists(lists[mid:]), mergeKLists(lists[:mid])}) }
|
三、思路二
优先队列
建立优先队列(大根堆或者小根堆均可),每次让链表头元素入队,一轮比较后,如果该元素被弹出,对应的链表则后移,后面的元素再入队。
代码实现
>folded main.go1 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
| func mergeKLists2(lists []*ListNode) *ListNode { if lists == nil || len(lists) == 0 { return nil }
var h MinHeap heap.Init(&h)
for _, l := range lists { if l != nil { heap.Push(&h, l) } }
dummy := &ListNode{} p := dummy
for h.Len() > 0 { min := heap.Pop(&h).(*ListNode) p.Next = min p = p.Next if min.Next != nil { heap.Push(&h, min.Next) } } return dummy.Next }
|