148. 排序链表*【力扣】

题意理解

对一个链表排序,要求时间复杂度O(nlogn)

问题分析

用归并 + 快慢指针

归并的套路是先分块排序,再合并排序。用快慢指针分块。

其他

https://blog.csdn.net/Scarlett_Guan/article/details/79435552

链接

    ListNode* sortList(ListNode* head) {
        if (!head || !head -> next) {    //空链表或1个结点链表
            return head;    //直接返回链表
        }  
        /*
        ListNode* pp = head;
        while (pp) {
            cout << pp -> val;
            pp = pp -> next;
        }
        cout << endl;
        */
        ListNode *slow = head;    //慢指针,初始化指向第一个结点
        ListNode *fast = head;    //快指针,初始化指向第一个结点
        ListNode *pre = head;    //指向慢指针前一个位置
        while (fast && fast -> next) {    //向后走两步,(已经判断可以走)
            pre = slow;    //保留慢指针前一个结点
            slow = slow -> next;    //慢指针走一步
            fast = fast -> next -> next;    //快指针走两步
        }
        pre -> next = nullptr;    //慢指针来分隔
        head = sortList (head);    //递归排序前半链表
        slow = sortList (slow);    //递归排序后半链表
        return mergeList (head, slow);    //合并前后半个链表
    }
    ListNode* mergeList (ListNode* head1, ListNode* head2) {
        ListNode* dummy = new ListNode(0);    //虚拟头结点,方便合并(key)
        ListNode* p = dummy;    //后移指针
        while (head1 && head2) {    //链表双指针都存在
            if (head1 -> val <= head2 -> val) {    //前链表小
                p -> next = head1;    //前链表当前指针结点连上合并后的结点
                head1 = head1 -> next;    //前链表后移
            }
            else {    //否则
                p -> next = head2;    //后链表当前指针结点连上合并和的结点
                head2 = head2 -> next;    //后链表后移
            }
            p = p -> next;    //合并后的链表后移
        }
        if (head1) {    //如果前链表还存在
            p -> next = head1;    //连上合并后的链表
        }
        if (head2) {    //如果后链表还存在
            p -> next = head2;    //连上合并后的链表
        }
        return dummy -> next;    //虚拟头结点去掉后的链表返回
    }

 

你可能感兴趣的:(算法,工作刷题)