Given the head
of a linked list, return the list after sorting it in ascending order.
Example 1:
Input: head = [4,2,1,3] Output: [1,2,3,4]
Example 2:
Input: head = [-1,5,3,4,0] Output: [-1,0,3,4,5]
Example 3:
Input: head = [] Output: []
Constraints:
- The number of nodes in the list is in the range
[0, 5 * 104]
. -105 <= Node.val <= 105
Follow up: Can you sort the linked list in O(n logn)
time and O(1)
memory (i.e. constant space)?
这题还是要求对链表做排序,不像147. Insertion Sort List 指定要用插入排序。这题可以自己选择排序算法,但要求时间复杂度是O(n*logn),很显然插入排序的O(n^2)无法满足要求。试跑了一下147. Insertion Sort List 的代码果然超时。
由于指定要达到O(n*logn),在众多排序算法中首先想到的会是归并排序(merge sort),其核心思想就是把链表从中间分成两部分,如果两部分都是有序的那就可以重新合并使整个链表是有序的,前面已经刷过如何合并两个有序链表的题LeetCode 21. Merge Two Sorted Lists。
如何使链表前后两部分变成有序的呢?可以分别把它们再各自分成两部分,一直递归调用下去,当最后两部分都只有一个节点时那就肯定是有序的了,然后依次合并返回,返回到了最上层合并之后整个链表就已经排好序了。
如何把链表从中间分成前后两部分呢?找到链表的中间节点,从中间节点断开就把链表分成了两个部分了。对于获取中间节点可以用快慢指针法。注意在使用快慢指针时,一开始快指针要指向第二节点,这样只剩两个节点时可以分成两部分各含一个节点,以免造成死循环。另外要注意的是分成两部分后前半部分的最后一个节点(中间节点)的next要指向空,以免递归调用时无法停止。
# 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
def getMid(h):
if not h or not h.next:
return h
slow, fast = h, h.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
mid = getMid(head)
h1, h2 = head, mid.next
mid.next = None
h1 = self.sortList(h1)
h2 = self.sortList(h2)
preHead = ListNode(-1)
cur = preHead
while h1 and h2:
if h1.val < h2.val:
cur.next = h1
h1 = h1.next
else:
cur.next = h2
h2 = h2.next
cur = cur.next
cur.next = h1 if h1 else h2
return preHead.next
,