打败算法 —— 排序链表

本文参考

出自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

posted @ 2022-03-05 16:59  咕~咕咕  阅读(207)  评论(0编辑  收藏  举报