Leetcode P0148"Sort List" 题解

2020/09/17 Leetcode

博文中会简要介绍Leetcode P0148题目分析及解题思路。

“Sort List”是一道比较经典的利用归并排序的题目。这道题要求时间复杂度是O(nlogn)。

其实看到O(nlogn)这样的时间复杂度,除了归并排序(Merge Sort)以外,还能想到快排序(Quick Sort)。但是后者是平均时间复杂度为O(nlogn),最坏时间复杂度是O(n^2),考虑到这题中是链表排序,无法随机选择pivot,如果每次都选择最左边的作为pivot,但是不巧地遇到一个降序序列,那么快排序就会退化为插入排序,变成O(n^2)的时间复杂度。所以这道题优先考虑使用归并排序。

Given the head of a linked list, return the list after sorting it in ascending order.

Follow up: Can you sort the linked list in O(n logn) time and O(1) memory (i.e. constant space)?

以下是Java的题解代码实现。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null)
            return head;
        
        return this.mergeSort(head);
    }
    
    private ListNode mergeSort(ListNode head) {
        if (head.next == null)
            return head;
        
        ListNode slow = head, fast = head.next;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        
        // Split the linked list into two parts
        ListNode half = slow.next;
        slow.next = null;
        
        ListNode l1 = this.mergeSort(head);
        ListNode l2 = this.mergeSort(half);
        
        return this.merge(l1, l2);
    }
    
    private ListNode merge(ListNode l1, ListNode l2) {
        ListNode l3 = new ListNode(0), tail = l3;
        
        while (l1 != null && l2 != null) {
            tail.next = (l1.val <= l2.val)? l1: l2;
            
            tail = tail.next;
            l1 = (tail == l1)? l1.next: l1;
            l2 = (tail == l2)? l2.next: l2;
        }
        
        if (l1 != null)
            tail.next = l1;
        
        if (l2 != null)
            tail.next = l2;
        
        return l3.next;
    }
}

以下是C++的题解代码实现。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if (!head)
            return head;
        
        return this->_MergeSort(head);
    }

private:
    ListNode* _MergeSort(ListNode *head) {
        if (!head->next)
            return head;
        
        ListNode *slow = head, *fast = head->next;
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
        }
        
        ListNode *half = slow->next;
        slow->next = nullptr;
        
        ListNode *l1 = this->_MergeSort(head);
        ListNode *l2 = this->_MergeSort(half);
        
        return this->_Merge(l1, l2);
    }
    
    ListNode *_Merge(ListNode *l1, ListNode *l2) {
        ListNode *l3 = new ListNode(0), *tail = l3;
        
        while (l1 && l2) {
            tail->next = (l1->val <= l2->val)? l1: l2;
            
            tail = tail->next;
            l1 = (tail == l1)? l1->next: l1;
            l2 = (tail == l2)? l2->next: l2;
        }
        
        if (l1)
            tail->next = l1;
        if (l2)
            tail->next = l2;
        
        return l3->next;
    }
};

Search

    Table of Contents