思路
1、归并排序+双指针
归并排序:递归,涉及划分左右区间;合并区间,涉及左右指针,类似合并两个排序的链表
- 递归
1、终止条件: 当子链表划分到为空或者只剩一个节点时,不再继续划分,往上合并。
2、递归函数入参和返回值: 入参:链表头结点,返回值:每次返回两个排好序且合并好的子链表。
3、本层逻辑: 找到这个链表的中间节点,从前面断开,分为左右两个子链表,进入子问题排序。 - 如何找中间结点?
准备三个指针,快指针right每次走两步,慢指针mid每次走一步,前序指针left每次跟在mid前一个位置。三个指针遍历链表,当快指针到达链表尾部的时候,慢指针mid刚好走了链表的一半,正好是中间位置。
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param head ListNode类 the head node
# @return ListNode类
#
class Solution:
#合并两段有序链表
def merge(self, phead1, phead2):
#一个已空,直接返回另一个
if phead1 == None:
return phead2
if phead2==None:
return phead1
#虚拟表头
dummy_head=ListNode(0)
cur=dummy_head
#两个表都不为空
while phead1 and phead2:
if phead1.val <= phead2.val:
cur.next=phead1
#只移动取值的指针
phead1=phead1.next
else:
cur.next=phead2
phead2=phead2.next
#指针后移
cur=cur.next
#哪个链表有剩,直接连在后面
if phead1:
cur.next=phead1
if phead2:
cur.next=phead2
return dummy_head.next
def sortInList(self , head: ListNode) -> ListNode:
# 1、归并排序:分治+双指针
#链表为空或只有一个元素,直接有序
if head==None or head.next==None:
return head
#前序指针指向mid的前一个位置
left=head
#慢指针指向中间位置
mid=head.next
#快指针,每次走2步
right=head.next.next
#右指针到链表尾时,mid指针在链表中间
while right and right.next:
left=left.next
mid=mid.next
right=right.next.next
#前序指针指向左端最右的一个节点,从这里断开
left.next=None
#分成2段排序,合并排序好的段
return self.merge(self.sortInList(head), self.sortInList(mid))
2、链表转数组
链表转数组
数组排序
排序后的数组转链表
时间复杂度:O(nlogn)sort函数一般为优化后的快速排序,复杂度为O(nlogn)
空间复杂度:O(n),存储链表元素值的辅助数组长度n
class Solution:
def sortInList(self , head: ListNode) -> ListNode:
# 2、转为数组排序
#为空处理
# if head is None or head.next is None:
# return head
# p=head
# nums=[]
# #遍历链表,将结点值加入数组
# while p:
# nums.append(p.val)
# p=p.next
# #数组排序
# nums.sort()
# p=head
# #遍历数组,将排序后的值加入链表
# for i in range(len(nums)):
# p.val=nums[i]
# p=p.next
# return head