这是一道很好的面试题。考察了链表、排序等基本数据结构的使用。同时还融合了递归(分治)的思想。同时分析归并排序的复杂度也不是一件很轻松的事情,值得学习。

1.  题目

2. 分析

本题的难点在于分析时间复杂度和空间复杂度。

3. 代码

3.1 自顶向下的归并排序

# 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 head and head.next is None:
            return head
        if head is None:
            return None
        # 采用分治的思想解决这道题
        head1, head2 = self.split_list(head)
        new_head1 = self.sortList(head1)
        new_head2 = self.sortList(head2)
        new_head = self.merge_two_list(new_head1, new_head2)
        return new_head

    def split_list(self, head):
        head1 = head
        slow = fast = head
        while(fast.next and fast.next.next):
            slow = slow.next
            fast = fast.next.next
        head2 = slow.next
        slow.next = None
        return head1, head2

    # 合并两个有序链表
    def merge_two_list(self, head1, head2):
        head = None
        if head1.val < head2.val:
            head = head1
            head1 = head1.next
        else:
            head = head2
            head2 = head2.next
        head_bak = head
        # 开始衔接两个链表
        while(head1 and head2):
            if head1.val < head2.val:
                head.next = head1
                head1 = head1.next
            else:
                head.next = head2
                head2 = head2.next
            head = head.next
            head.next = None
        
        if(head1):
            head.next = head1
        if head2:
            head.next = head2
        return head_bak
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.

上面这个代码的复杂度分别是:

  • 时间复杂度:O(NlogN)
  • 空间复杂度:O(logN)