打败算法 —— 排序链表
本文参考
出自LeetCode上的题库 —— 排序链表
https://leetcode-cn.com/problems/sort-list/
排序问题
给定链表的头结点 head ,按升序排列并返回排序后的链表
示例1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:
输入:head = []
输出:[]
解题思路
题干非常容易理解,就是对单向链表进行排序,和数组不同的是,我们不能在排序过程中随机访问链表中的每一个元素,因此无法应用需要向左遍历的排序方法,如快速排序。和快速排序具有相同时间复杂度$O(nlogn)$的归并排序是个不错的选择,我们可以先通过快慢指针将常链表分为前后两个部分,然后递归调用排序函数,是十分容易理解的分治思想。最后的merge函数也同常规的归并算法类似。
归并排序解法
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next: ListNode = next
class Solution:
def sort_list(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 空链表或仅有一个结点的链表
if head is None or head.next is None:
return head
# 仅有两个结点的链表
if head.next.next is None:
if head.val > head.next.val:
head.val, head.next.val = head.next.val, head.val
return head
# 利用快慢指针将链表分为两个部分
slow = fast = head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
front = head
back = slow.next
slow.next = None
# 分治
front = self.sort_list(front)
back = self.sort_list(back)
# 合并
return self.merge(front, back)
def merge(self, front: ListNode, back: ListNode):
head = ListNode()
curr = head
while front and back:
if front.val <= back.val:
curr.next = front
front = front.next
else:
curr.next = back
back = back.next
curr = curr.next
if front is None:
while back:
curr.next = back
curr = curr.next
back = back.next
else:
while front:
curr.next = front
curr = curr.next
front = front.next
return head.next