leetcode 148. 排序連結串列(歸併排序 快慢指標 遞迴 迭代)
阿新 • • 發佈:2021-10-07
連結:https://leetcode-cn.com/problems/sort-list/
題目
給你連結串列的頭結點head,請將其按 升序 排列並返回 排序後的連結串列 。
進階:
你可以在O(nlogn) 時間複雜度和常數級空間複雜度下,對連結串列進行排序嗎?
示例
示例 1:
輸入:head = [4,2,1,3]
輸出:[1,2,3,4]
示例 2:
輸入:head = [-1,5,3,4,0]
輸出:[-1,0,3,4,5]
示例 3:
輸入:head = []
輸出:[]
提示:
連結串列中節點的數目在範圍[0, 5 * 104]內
-105<= Node.val <= 105
思路
方法1
遞迴 實現歸併排序
使用快慢指標分割連結串列
由於使用遞迴O(logn)棧記憶體空間
class Solution { public: ListNode* sortList(ListNode* head) { if(!head||head->next==nullptr) return head; ListNode *front=head->next,*back=head; int index=0; while(front->next) { front=front->next; index++; if(index%2==0) { back=back->next; index=0; } } front=back->next; back->next=nullptr; return sort(sortList(head),sortList(front)); } ListNode*sort(ListNode*a,ListNode*b) { ListNode*ha=a,*hb=b; ListNode*ptr=nullptr; if(ha->val<=hb->val) { ptr=ha; ha=ha->next; }else { ptr=hb; hb=hb->next; } ListNode *head=ptr; while(ha!=nullptr&&hb!=nullptr) { if(ha->val<=hb->val) { ptr->next=ha; ha=ha->next; }else{ ptr->next=hb; hb=hb->next; } ptr=ptr->next; } if(ha!=nullptr) { ptr->next=ha; } if(hb!=nullptr) { ptr->next=hb; } return head; } };
方法2
由於進階要求常數級空間複雜度 所以不能用遞迴
可以手動分割等長連結串列 迭代
class Solution { public: ListNode* sortList(ListNode* head) { if(!head||head->next==nullptr) return head; int num=0; ListNode*ptr=head; while(ptr) { num++; ptr=ptr->next; } ListNode *dhead=new ListNode(0,head);//定義頭節點 for(int lenth=1;lenth<num;lenth<<=1) { ListNode *pre=dhead,*cur=dhead->next;//定義分支的頭節點和 流動的節點 while(cur!=nullptr)//當前節點不為空 { ListNode *head1=cur; for(int i=1;i<lenth&&cur->next!=nullptr;++i) { cur=cur->next; } ListNode *head2=cur->next; cur->next=nullptr; cur=head2; for(int i=1;i<lenth&&cur!=nullptr&&cur->next!=nullptr;++i) { cur=cur->next; } ListNode *n =nullptr; if(cur!=nullptr) { n=cur->next; cur->next=nullptr; } pre->next=merge(head1,head2); while(pre->next!=nullptr){ pre=pre->next; } cur=n; } } return dhead->next; } ListNode* merge(ListNode* head1, ListNode* head2) { ListNode* dummyHead = new ListNode(0); ListNode* temp = dummyHead, *temp1 = head1, *temp2 = head2; while (temp1 != nullptr && temp2 != nullptr) { if (temp1->val <= temp2->val) { temp->next = temp1; temp1 = temp1->next; } else { temp->next = temp2; temp2 = temp2->next; } temp = temp->next; } if (temp1 != nullptr) { temp->next = temp1; } else if (temp2 != nullptr) { temp->next = temp2; } return dummyHead->next; } };
注意
連結串列問題可以定義額外頭節點來 規範迴圈條件ListNode *dhead=new ListNode(0,head);