**23. Merge k Sorted Lists

1. 原始题目

合并 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

2. 解题

思路1. 优先队列。即自动排序的队列。

将所有链表结点依次进队,此时结点已排好序,再分别出队组成新链表即可。

注:python3的优先队列:

from queue import PriorityQueue

有了优先队列,这个题就是easy了:

 1 class Solution:
 2     def mergeKLists(self, lists: List[ListNode]) -> ListNode:
 3         q = PriorityQueue()
 4         dummy = ListNode(None)
 5         head = dummy
 6         for node in lists:
 7             while(node):
 8                 q.put(node.val)
 9                 node = node.next
10         while not q.empty():
11             dummy.next = ListNode(q.get())
12             dummy = dummy.next
13             
14         dummy.next = None
15         
16         return head.next

 

思路2.DP动态规划

首先递归实现两个链表的合并:

 1     def MergeTwoList(self,phead1,phead2):
 2         if not phead1: return phead2
 3         if not phead2: return phead1
 4         node = ListNode(0)
 5         
 6         if phead1.val>phead2.val:
 7             node = phead2       # 指向一个新结点
 8             node.next = self.MergeTwoList(phead1,phead2.next)  # 合并一个两个新的链表
 9         else:
10             node = phead1 
11             node.next = self.MergeTwoList(phead1.next,phead2)
12         return node

接着动态规划实现多个链表的合并:思路是列表中k个链表的合并,可以看作两个子列表的合并,即 0~k/2 这个列表中的链表 和 k/2~k个列表中的链表的合并。

然后继续将两个子列表折半,再折半...停止递归的条件有三个:空列表返回None;列表中只有1个元素,返回该单个链表;列表中只有2个元素,调用两个链表合并的函数实现合并!

整体代码如下:

 1 class Solution:
 2     def MergeTwoList(self,phead1,phead2):        # 合并两个链表
 3         if not phead1: return phead2
 4         if not phead2: return phead1
 5         node = ListNode(0)
 6         
 7         if phead1.val>phead2.val:
 8             node = phead2
 9             node.next = self.MergeTwoList(phead1,phead2.next)
10         else:
11             node = phead1
12             node.next = self.MergeTwoList(phead1.next,phead2)
13         return node
14     
15     def mergeKLists(self, lists) -> ListNode:          # 合并多个链表
16         
17         if len(lists)==0: return None                  # 递归停止的第一个条件
18         if len(lists)==1: return lists[0]              # 递归停止的第二个条件
19         if len(lists)==2: return self.MergeTwoList(lists[0], lists[1])      # 递归停止的第三个条件
20         mid = int(len(lists)/2)    # 列表中的所有链表分成两部分
21         node1 = []
22         for i in range(mid):         # 左边一半
23             node1.append(lists[i])
24         node2 = []
25         for i in range(mid,len(lists)):         # 右边一半
26             node2.append(lists[i])
27         
28         return self.MergeTwoList(self.mergeKLists(node1), self.mergeKLists(node2))     # 这句话最关键!两个子列表合并完之后,实现两个链表的合并!

 

 验证:

 1 # 新建链表1
 2 listnode1 = ListNode_handle(None)
 3 s1 = [2,7,26,47,86,90]
 4 for i in s1:
 5     listnode1.add(i)
 7 listnode1.print_node(listnode1.head)
 8 
 9 # 新建链表2
10 listnode2 = ListNode_handle(None)
11 s2 = [1,5,6,78,92]
12 for i in s2:
13     listnode2.add(i)
14 listnode2.print_node(listnode2.head)
15 
16 # 新建链表3
17 listnode3 = ListNode_handle(None)
18 s3 = [12,15,16,178,192]
19 for i in s3:
20     listnode3.add(i)
21 listnode3.print_node(listnode3.head)

    s=Solution()
    listnode1.print_node(s.mergeKLists([listnode1.head, listnode2.head, listnode3.head]))

2 7 26 47 86 90
1 5 6 78 92
12 15 16 178 192
1 2 5 6 7 12 15 16 26 47 78 86 90 92 178 192

 

posted @ 2019-04-10 18:13  三年一梦  阅读(513)  评论(0)    收藏  举报