148.排序链表,23.合并K个升序链表
链表中使用递归来实现分治的方法。实现方法都挺巧妙的,记录一下。
排序链表
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:if not head or not head.next:return head### 1. 插入排序法。时间复杂度O(n2)# dummy_head = ListNode(val=0)# dummy_head.next = head# lastSorted = head# curr = lastSorted.next# while curr:# if curr.val > lastSorted.val:# lastSorted = lastSorted.next# curr = lastSorted.next# else:# prev = dummy_head# while curr.val > prev.next.val:# prev = prev.next# ### 此时curr要插在prev之后# lastSorted.next = curr.next# curr.next = prev.next# prev.next = curr# curr = lastSorted.next# return dummy_head.next## 2. 自顶向下归并,每次获得一个链表就先将链表切分为2分,进行排序后再合并return self.sortFunc(head, None) ### tail 为 Nonedef sortFunc(self, head: Optional[ListNode], tail: Optional[ListNode]):"""对子链表进行排序"""if not head: ### 空链表return headif head.next == tail: ## 单节点链表,此时是最小分割边缘head.next = None ## 切分两部分子链表的连接关系,后续merge才不会出错return head slow = fast = headwhile fast != tail:slow = slow.nextfast = fast.nextif fast != tail:fast = fast.nextmid = slowreturn self.merge(self.sortFunc(head,mid), self.sortFunc(mid, tail)) #### 切分成两个区间, [head, mid) 和 [mid, tail)def merge(self, head1, head2):dummy_head = ListNode(0)temp, temp1, temp2 = dummy_head, head1, head2### Z形合并while temp1 and temp2:if temp1.val > temp2.val:temp.next = temp2temp2 = temp2.nextelse:temp.next = temp1temp1 = temp1.nexttemp = temp.nexttemp.next = temp1 if temp1 else temp2return dummy_head.next
合并K个升序链表
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = nextimport heapq
class Solution:def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:if not lists: ## 空数组return Noneif len(lists) == 1: ## 数组里只有一个链表return lists[0]### 暴力方法# store_list = []# for i in range(len(lists)):# curr_head = lists[i]# while curr_head:# store_list.append(curr_head.val)# curr_head = curr_head.next# store_list.sort()# dummy_node = ListNode()# pre = dummy_node# for node_val in store_list:# pre.next = ListNode(val = node_val)# pre = pre.next# return dummy_node.next### 暴力方法优化————使用优先队列# queue = []# for i in range(len(lists)):# curr_head = lists[i]# while curr_head:# heapq.heappush(queue, curr_head.val) ### 这里是往优先级队列中填入节点的值进行排序# curr_head = curr_head.next# dummy_node = ListNode()# pre = dummy_node# while queue:# node_val = heapq.heappop(queue)# pre.next = ListNode(val = node_val)# pre = pre.next# return dummy_node.next### 进一步优化; 不通过重新创建节点的形式来进行后续的连接操作queue = []for i in range(len(lists)):curr_head = lists[i]lst = 0while curr_head:### 元组存储的是 (curr_head.val , i, curr_head),存在问题,但前两个值相同时,此时node是无法比较大小的。可以引入一个新的变量,来使得根据三个变量可以唯一确定node的大小heapq.heappush(queue, (curr_head.val, i, lst, curr_head)) ### 这里是往优先级队列中填入节点的值进行排序。但是保存是一个元祖,存储了节点的信息, i表示数组索引,lst表示节点(其后续还连着其他节点)curr_head = curr_head.nextlst += 1dummy_node = ListNode()pre = dummy_nodewhile queue:node_val, list_index, lst, node = heapq.heappop(queue)node.next = Nonepre.next = nodepre = pre.nextreturn dummy_node.next### 思路1,顺序合并。 逐一比较。# merge_head = lists[0]# for i in range(1,len(lists)): # merge_head = self.merge(merge_head, lists[i])# return merge_head### 思路2,分治# amount = len(lists) ### 记录链表的数目# pre, tail = 0, len(lists) - 1# return self.mergeLists(pre, tail, lists)def mergeLists(self, pre, tail, lists):####递归方式实现分治法if pre == tail:return lists[pre]head1 = lists[pre]head2 = lists[tail]if pre + 1 == tail:return self.merge(head1, head2)else:mid = (pre + tail) // 2return self.merge(self.mergeLists(pre, mid, lists), self.mergeLists(mid+1, tail, lists))def merge(self, head1, head2):### 将head1和head2进行合并后输出dummy_node = ListNode()temp, temp1, temp2 = dummy_node, head1, head2while temp1 and temp2:if temp1.val > temp2.val:temp.next = temp2temp2 = temp2.nextelse:temp.next = temp1temp1 = temp1.nexttemp = temp.nexttemp.next = temp1 if temp1 else temp2return dummy_node.next