【题目描述】算法
对链表进行排序,方法不少,因为要求时间复杂度是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
复制代码