Leetcode 148. Sort List
题目
Sort a linked list in O(n log n) time using constant space complexity.
Example 1:
Input: 4->2->1->3
Output: 1->2->3->4
Example 2:
Input: -1->5->3->4->0
Output: -1->0->3->4->5
解法1:利用最小堆
循环一次整个链表,将node的值存入一个最小堆中,再循环这个最小堆,将元素一次pop出来,构建新链表
class Solution(object):
def sortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
l = []
while head:
heapq.heappush(l,head.val)
head = head.next
first_val = heapq.heappop(l)
first = ListNode(first_val)
tmp = first
while l:
curr_val = heapq.heappop(l)
tmp.next = ListNode(curr_val)
tmp = tmp.next
return first
时间复杂度:O(Nlog(N))
空间复杂度:O(N),需要构建一个最小堆
解法2:利用归并排序的思想
题目要求的是constant space,换句话说就是O(1)的空间复杂度,所以严格意义上来讲解法1是不符合要求的,但是单从时间上来讲,出来的结果解法1更快。
为了符合空间复杂度的要求,这里采用了归并排序的思想,但是由于链表特殊的形式,不需要额外开辟数组空间储存已经merge完成的子列表,而只需储存已经排序好的子链表的头即可,这样就实现了要求的空间复杂度。
这边还利用到了双指针法的一个特性,**设置slow和fast指针,开始它们都指向表头,fast每次走两步,slow每次走一步,fast到链表尾部时,slow正好到中间,这样就将链表截为两段。**这个操作非常常见,在leetcode141和142中也有出现,可做对比
class Solution(object):
def sortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
def merge(head1,head2):
if not head1:
return head2
if not head2:
return head1
dummy = ListNode(0)
tmp = dummy
while head1 and head2:
if head1.val<head2.val:
tmp.next = head1
head1 = head1.next
tmp = tmp.next
else:
tmp.next = head2
head2 = head2.next
tmp = tmp.next
if not head1:
tmp.next = head2
if not head2:
tmp.next = head1
return dummy.next
if not head or not head.next:
return head
slow = head;fast = head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
lefthead = head
righthead = slow.next
slow.next = None
lefthead = self.sortList(lefthead)
righthead = self.sortList(righthead)
head = merge(lefthead,righthead)
return head
时间复杂度:O(Nlog(N))
空间复杂度:O(1)