【題目描述】算法
對鏈表進行排序,方法不少,因爲要求時間複雜度是O(nlogn)空間複雜度是常量級別,因此咱們須要在衆多排序中作選擇,知足這個時間複雜度的排序算法有快速排序,堆排序,希爾排序和歸併排序。因爲快排在最壞狀況下的時間複雜度是O(n*n)因此不知足,考慮到是鏈表,不能用數字來指示位置了,所以咱們選擇歸併排序。bash
歸併排序就是不斷找到當前鏈表的中點,把他拆分紅兩部分,再對這兩部分不斷拆分,直至每段只剩下兩個值爲止,對這兩個值進行排序,而後不斷返回上層排序。說白了就是先兩個兩個比,而後四個四個比,而後8個8個比,最後把整個鏈表排序完畢。函數
先寫一個鏈表找中點的函數,用快慢指針的辦法,快指針和慢指針都從頭部開始,慢指針一次走一步,快指針一次走兩步,當快指針走到他的next的next是空,就停下,此時慢指針走到的位置就是中間部位。返回值是中間指針。ui
def getmid(self,head):#鏈表快慢指針找中點
slow=fast=head
if head is None :return slow
while fast.next and fast.next.next:
slow=slow.next
fast=fast.next.next
return slow
複製代碼
再寫一個排序函數,對兩個鏈表進行排序,以後再返回排序以後的頭指針spa
def merge(self,l,r):
a=ListNode(0)
q=a
while l and r:
if l.val>r.val:
q.next=r
r=r.next
else:
q.next=l
l=l.next
q=q.next
if l:
q.next=l
if r:
q.next=r
return a.next
複製代碼
在主函數中,遞歸調用自身,主函數執行的邏輯是找中間指針,而後將這個鏈表短成兩段,並用l表示前一段的頭指針,r表示後一段的頭指針,指針
def sortList(self, head):
""" :type head: ListNode :rtype: ListNode """
if head is None or head.next is None:return head
mid=self.getmid(head)
l=head
r=mid.next
mid.next=None
return self.merge(self.sortList(l),self.sortList(r))
複製代碼
【源代碼】 歸併排序code
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def sortList(self, head):
""" :type head: ListNode :rtype: ListNode """
if head is None or head.next is None:return head
mid=self.getmid(head)
l=head
r=mid.next
mid.next=None
return self.merge(self.sortList(l),self.sortList(r))
def getmid(self,head):#鏈表快慢指針找中點
slow=fast=head
if head is None :return slow
while fast.next and fast.next.next:
slow=slow.next
fast=fast.next.next
return slow
def merge(self,l,r):
a=ListNode(0)
q=a
while l and r:
if l.val>r.val:
q.next=r
r=r.next
else:
q.next=l
l=l.next
q=q.next
if l:
q.next=l
if r:
q.next=r
return a.next
複製代碼