先看题目:
因为时间复杂度是nlogn,所以采用二分法。假设是n = 2^k个输入,经过二分法,有 k = logn层。每一层排序的时间复杂度是n,故整体时间复杂度是nlogn。
方法一:
在 left, right = self.sortList(head), self.sortList(mid)之前实现二分法操作,分到最小单元,即left = None,right = None,之后实现排序操作,再合并,循环,直到head =None或head.next== None。
#归并排序,递归法。
#通过二分法得到最小节点单元,直到left.next = None and right.next = None.然后开始合并
class ListNode(object):
def __init__(self, val, next=None):
self.val = val
self.next = next
class Solution:
def sortList(self, head):
if head == None or head.next == None:
return head # termination.
slow, fast = head, head.next#快指针走的是慢指针的两倍,故慢指针可以找到中点。
while fast and fast.next:
fast, slow = fast.next.next, slow.next
mid, slow.next = slow.next, None
left, right = self.sortList(head), self.sortList(mid)#递归操作
h = res = ListNode(0)
while left and right:
if left.val < right.val:
h.next = left
left = left.next
else:
h.next = right
right = right.next
h = h.next
h.next = left if left else right
return res.next
方法二:
利用pre和pre.next不断存储更新链表。
定位h,找到h1,h2,比较二者大小,不断更新pre和pre.next,直到head= None。
#归并排序,自底部至顶部
#没有用到递归操作
class ListNode(object):
def __init__(self, val, next=None):
self.val = val
self.next = next
class Solution:
def sortList(self, head):
h, length, intv = head, 0, 1 #统计出长度
while h:
h, length = h.next, length + 1# 分成最最小单元
res = ListNode(0)
res.next = head
while intv < length:
pre, h = res, res.next
while h:# h1, h2#当h存在时
h1, i = h, intv #找到h1
while i and h:
h, i = h.next, i - 1
if i:
break ##当i不为0,但是head=None
h2, i = h, intv #找到h2
while i and h:
h, i = h.next, i - 1
c1, c2 = intv, intv - i # c1和c2分别是h1和h2的单元长度。c2 的长度小于等于intv的长度。
while c1 and c2: #排序
if h1.val < h2.val:
pre.next, h1, c1 = h1, h1.next, c1 - 1#反复比较h1 和 h2 ,当h1.next存在时,h1.next和h2继续比较
else:
pre.next, h2, c2 = h2, h2.next, c2 - 1
pre = pre.next
pre.next = h1 if c1 else h2
while c1 > 0 or c2 > 0:#找到下一次和h
pre, c1, c2 = pre.next, c1 - 1, c2 - 1
pre.next = h
intv *= 2
return res.next
反复debug,直到完全明白递归操作是怎么实现的。链表的排序因为有self.next=next,故直接变换其接下来的地址即可。
也可查看详细解释:
Sort List (归并排序链表)