---
# System prepended metadata

title: 'LeetCode #148 [Sort List](https://leetcode.com/problems/sort-list/) - Advanced'
tags: [LeetCode, Medium, Linked List, Merge Sort]

---

###### tags: `LeetCode` `Linked List` `Medium` `Merge Sort`
# LeetCode #148 [Sort List](https://leetcode.com/problems/sort-list/) - Advanced
### (Medium)

給你鏈結串列的頭結點 head，請將其按 升序 排列並返回排序後的鏈結串列。

![](https://i.imgur.com/g83KneM.png)

---
依照題目要求, 需在時間複雜度O(nlogn), 空間複雜度O(1)的情況下完成。

![](https://i.imgur.com/OF40gvU.png)

可以看到, 唯一能滿足的方法只有bottom up的merge sort。

使用split搭配for迴圈:
* for迴圈初始為i=1, 每次遞迴後i<<=1, 代表i左移一格(乘以2)。
* split函式的參數為(ListNode* head, int n), n代表這串鍊結串列的長度, 也就是說以head開始往後數n個節點, 宣告一指標指向該節點下一個元素後, 將該節點的next指向nullptr(也就是斷開節點), 然後回傳新宣告的指標。

比如說 3->2->4->1, n=2, split完後會變成3->2 & 4->1, 並返回指向4的指標。

然後將切完的節點傳入merge中, merge函式會進行排序(每次只要比較兩指標節點的第一個元素即可), 排序完後回傳pair<ListNode*, ListNode*>分別代表head指標與tail指標, 將指標頭尾相接後進行下一輪split&merge, 一次切割的數量大於整個鏈結串列的長度, 此時回傳指向鏈結串列第一個元素的指標即可。

---
```
/**
 * 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||!head->next)return head;
        int len=1;
        ListNode* cur = head;
        while(cur){
            len++;
            cur=cur->next;
        }
        ListNode *l, *r, *tail;
        ListNode dummy(0);
        dummy.next = head;
        for(int n=1;n<len;n<<=1){
            cur=dummy.next;
            tail=&dummy;
            while(cur){
                l=cur;
                r=split(l, n);
                cur=split(r, n);
                auto merged = merge(l, r);
                tail->next=merged.first;
                tail=merged.second;
            }
        }
        return dummy.next;
    }
    ListNode* split(ListNode* head, int n){
        //return rest nodes' head
        while(--n&&head){
            head=head->next;
        }
        ListNode* rest = head?head->next:nullptr;
        if(head)head->next = nullptr;
        return rest;
    }
    pair<ListNode*, ListNode*> merge(ListNode* l1, ListNode* l2){
        //return head, tail
        ListNode dummy(0);
        ListNode* tail = &dummy;
        while(l1&&l2){
            if(l1->val>l2->val)swap(l1,l2);
            tail->next = l1;
            l1=l1->next;
            tail = tail->next;
        }
        tail->next = l1?l1:l2;
        while(tail->next)tail=tail->next;
        return {dummy.next, tail};
    }
};
```