算法练习-归并排序链表

69 阅读2分钟

题目如题,但是题目推荐在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

O(nlogn)O(nlogn) => 归并排序 or 快排

归并和快排都是分治的思想,所以一开始尝试用快排,但是实现到一半发现非常复杂,遂改用分治。

思路

分治是不断递归二分链表,直到成为单个节点,然后再通过合并函数有序合并元素,总结而言: 1.查找中心节点,二分调用自身 2.合并左右二分的链表为有序链表

重点

既然要二分,不可避免要查找链表到中心节点,这里查找中心节点使用的是快慢指针,快指针一次走两格。

踩坑点是:如果链表是偶数个节点,那么快慢指针从同一个起点走,找到的中间节点就会是右半部分的起始节点,导致在链表节点数为偶数时,左右两部分划分不合理。 这里应该让快指针初始化时,多走一步。

实现

/**
 * 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* merge(ListNode* list1, ListNode* list2) {
        ListNode head;
        ListNode *prev = &head;
        ListNode *pList1Node = list1, *pList2Node = list2;
        while (pList1Node && pList2Node) {
            if (pList1Node->val < pList2Node->val) {
                prev->next = pList1Node;
                pList1Node = pList1Node->next;
            }
            else {
                prev->next = pList2Node;
                pList2Node = pList2Node->next;
            }
            prev = prev->next;
        }
        if (pList1Node) {
            prev->next = pList1Node;
        }

        if (pList2Node) {
            prev->next = pList2Node;
        }
        return head.next;
    }

    ListNode* getMidNode(ListNode* head) {
        if (!head) { return head; }

        ListNode* quick = head->next;
        ListNode* mid = head;
        while (quick && quick->next) {
            mid = mid->next;
            quick = quick->next->next;
        }
        return mid;
    }

    ListNode* sortList(ListNode* head) {
        if (!head || !head->next) { return head; }

        ListNode* mid = getMidNode(head);
        ListNode* left = head;
        ListNode* right = mid->next;
        mid->next  = nullptr;

        ListNode* leftSorted  = sortList(left);
        ListNode* rightSorted = sortList(right);
        return merge(leftSorted, rightSorted);
    }
};