题目:
给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
题目示例:
输入:head = [4,2,1,3] 输出:[1,2,3,4]
输入:head = [-1,5,3,4,0] 输出:[-1,0,3,4,5]
输入:head = [] 输出:[]
进阶:你可以在 O(n log n)
时间复杂度和常数级空间复杂度下,对链表进行排序吗?
代码(进阶-迭代)
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
#迭代
listlength=1 #归并长度
dummynode=ListNode()
dummynode.next=head#哨兵
h=head
listnodelength=0
while h: #统计链表长度
listnodelength+=1
h=h.next
while listlength<listnodelength: #当归并长度小于链表长度时进行归并
pre,h=dummynode,dummynode.next#pre是用来迭代新归并链表的,同时用于链接新的节点
while h:#当前节点有值,h是当前遍历节点
left=h#左边归并头节点
count=listlength
while h and count:#保证节点有值
h=h.next
count-=1
if count:
break #没有右边归并
right=h#右边归并头节点
count=listlength
while h and count:
h=h.next
count-=1
leftcount,rightcount=listlength,listlength-count
while leftcount and rightcount:#进行归并,不能以链表,因为左右相连
if left.val<right.val:
pre.next=left
left=left.next
leftcount-=1
else:
pre.next=right
right=right.next
rightcount-=1
pre=pre.next
if leftcount:
pre.next=left
else:
pre.next=right#归并后合并
while leftcount>0 or rightcount>0:#递归完当前长度
pre=pre.next
leftcount-=1
rightcount-=1
pre.next=h#当前链表的下一个节点是下一个归并排序的头节点
listlength*=2
return dummynode.next
代码逻辑:
因为题目进阶要求我们使用常数级空间复杂度,此时不能用递归,采用迭代方式,直接进行归并
归并思路,从长度为1开始,当归并长度大于等于链表长度说明归并完成
设置dummynode哨兵节点,pre前序指针,h遍历指针来进行操作,
其中Left指针指向左归并序列,right指向右归并序列
需要注意的点是,要注意当前归并序列是否满足归并长度,进行对应设置
在这里考虑用leftcount以及rightcount代表左右归并序列长度
代码(归并递归)
# 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#单节点或者不存在,结束分裂
slow,fast=head,head.next#快慢指针找中间值
while fast and fast.next:
slow=slow.next
fast=fast.next.next
mid=slow.next#中间值为慢指针的下一位
slow.next=None#断开
left,right=self.sortList(head),self.sortList(mid)#进行递归分解
dummynode=pre=ListNode()#定义哨兵节点
while left and right:#分解结束后回溯链接
if left.val<right.val:
pre.next=left
left=left.next
else:
pre.next=right
right=right.next
pre=pre.next
pre.next=left if left else right
return dummynode.next#返回头节点
代码逻辑:
在这里我们主要使用快慢指针进行链表的分解,快指针一次走两步,慢指针一次走一步
同时在合并时用哨兵节点记录我们当前的节点
时间复杂度O(nlogn)空间复杂度(logn)
代码(快排递归)NOAC因为在面对正序或者逆序,时间复杂度O(N2)
# 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]:
start=ListNode()#初始化节点
start.next=head#指向初始节点
hashmap={}#字典
count=-1
while start.next!=None:
count+=1#索引值
hashmap[count]=start.next
start=start.next
def partition(hashmap,left,right):
tmp=hashmap[left]
while left<right:
while left<right and hashmap[right].val>=tmp.val:
right-=1
hashmap[left]=hashmap[right]
while left<right and hashmap[left].val<=tmp.val:
left+=1
hashmap[right]=hashmap[left]
hashmap[left]=tmp
return left
def quicksort(hashmap,left,right):
if left<right:
mid=partition(hashmap,left,right)
quicksort(hashmap,left,mid-1)
quicksort(hashmap,mid+1,right)
quicksort(hashmap,0,count)
start=ListNode()
current=start
for i in range(count+1):
current.next=hashmap[i]
current=current.next
current.next=None
return start.next