###### tags: `Leetcode` `medium` `list` `sort` `divide and conquer` `python` `c++` `Top 100 Liked Questions` # 148. Sort List ## [題目連結:] https://leetcode.com/problems/sort-list/description/ ## 題目: 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)? ![](https://i.imgur.com/XyPyX8V.png) ![](https://i.imgur.com/KWCaSKy.png) #### [圖片來源:] https://leetcode.com/problems/sort-list/description/ ## 解題想法: * 題目為要求排序list * time: 要求O(n logn) * space: 要求O(1) * 使用merge sort * (法1) topDowm: * 使用快慢pointer: 分兩段彼此再遞迴,最後再merge * time: O(NlongN) * space: O(n) * (法2)buttonUp: * 將元素兩兩merge,再兩兩merge.... * time: O(NlongN) * space: O(n) * 但有網路大神說可以到O(1)??? * 小的不才 不懂為啥不是O(N)是O(1)... * 思考: * 網路上標準解答都是用Top-down方法: * 且此題的歸類有 **divide and conquer** * 但這題要求O(1)的空間?? * 實際上應該**最多為O(n)而已** * 原因: * 添加新list Node數量會隨著遞歸次數增加,不是常數量 * 遞歸本身就不是常數空間 ## Python: * 可參考 [143. Reorder List](/YkakbugKSpyg0u8KQ-g2eQ) 作法 * 使用slow fast pointer: * 分兩段: 若遇**奇數** * **第一段少** * 第二段多 * 因為此題若讓第一段多,run and submit時會報錯誤(runtimeerror: maximum recursion depth exceeded) * P143為: 若遇奇數 第一段多 第二段少 ``` python= class ListNode(object): def __init__(self, val=0, next=None): self.val = val self.next = next def insert(self,node): if self.next==None: self.next=ListNode(node) else: self.next.insert(node) def printList(self): head=self stack=[] while head: stack.append(head.val) head=head.next print(stack) class Solution(object): def sortList(self, head): """ :type head: ListNode :rtype: ListNode """ #使用merge sort: #法1: topDowm: 使用快慢pointer: 分兩段彼此再遞迴,最後再merge # time: O(NlongN) space: O(n) if not head or not head.next: return head fast=head slow=head tail=None #first part's end while fast and fast.next: tail=slow slow=slow.next fast=fast.next.next #split two list tail.next=None #divide head1=self.sortList(head) head2=self.sortList(slow) return self.merge(head1,head2) def merge(self,head1,head2): dummy=ListNode(0) tail=dummy while head1 and head2: if head1.val<head2.val: tail.next=head1 tail=tail.next head1=head1.next else: tail.next=head2 tail=tail.next head2=head2.next tail.next=head1 if head1 else head2 return dummy.next if __name__=='__main__': head=ListNode(4) head.insert(2) head.insert(1) head.insert(3) print("Old :",end='') head.printList() #Old :[4, 2, 1, 3] result = Solution() ans = result.sortList(head) print("After:",end='') ans.printList() #After:[1, 2, 3, 4] ``` ## C++: ``` cpp= #include<iostream> #include<vector> using namespace std; 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) {} }; void InsertNode(ListNode *head, int data){ ListNode *tail=head; if (tail->next==nullptr){ ListNode *new_node= new ListNode(data); tail->next=new_node; } else InsertNode(tail->next,data); } void PrintList(ListNode *head){ vector<int> res; ListNode *tail=head; while (tail!=nullptr){ res.push_back(tail->val); tail=tail->next; } for (int i=0; i<res.size(); i++){ cout<<res[i]<<" "; } cout<<endl; } class Solution { public: ListNode* sortList(ListNode* head) { if (!head || !head->next) return head; ListNode *slow=head; ListNode *fast=head; ListNode *pre=nullptr; while (fast && fast->next){ pre=slow; slow=slow->next; fast=fast->next->next; } pre->next=nullptr; ListNode *head1=sortList(head); ListNode *head2=sortList(slow); return mergeList(head1,head2); } ListNode *mergeList(ListNode *head1, ListNode *head2){ ListNode *dummy=new ListNode(0), *tail=dummy; while (head1 && head2){ if (head1->val < head2->val){ tail->next=head1; tail=tail->next; head1=head1->next; } else{ tail->next=head2; tail=tail->next; head2=head2->next; } } tail->next=(head1!=nullptr)? head1 :head2; return dummy->next; } }; int main(){ ListNode *head=new ListNode(4); InsertNode(head,2); InsertNode(head,1); InsertNode(head,3); cout<<"Original List: "; PrintList(head); //Original List: 4 2 1 3 Solution res; ListNode *ans=res.sortList(head); cout<<"After Sorted : "; PrintList(ans); //After Sorted : 1 2 3 4 return 0; } ```