發現鏈表的歸併排序要注意的點還真挺多。
- 對元素的劃分,即要把鏈表從中間斷開,這個可以利用一個快指針每次走兩步,一個慢指針一次走一步的做法來實現,並記錄前半部分鏈表的最後一個節點。
- 對鏈表的合併,這個我是利用遞歸,很容易理解與實現。
代碼實現如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* MergeSort(ListNode* now) {
if (now == nullptr || now->next == nullptr)
return now;
ListNode* fast = now, * slow = now, * Break = now;
//注意這裏一定要兩個都要判斷。
while (fast != nullptr && fast->next != nullptr) {
fast = fast->next->next;
Break = slow;//這裏記錄的是前半部分的最後一個節點。
slow = slow->next;
}
Break->next = nullptr;
ListNode* l = MergeSort(now);
ListNode* m = MergeSort(slow);
return Merge(l, m);
}
ListNode* Merge(ListNode* l, ListNode* r) {
if (l == nullptr)
return r;
else if (r == nullptr)
return l;
else if (l->val <= r->val) {
l->next = Merge(l->next, r);
return l;//注意這裏要返回
}
else {
r->next = Merge(l, r->next);
return r;
}
return nullptr;
}
ListNode* sortList(ListNode* head) {
return MergeSort(head);
}
};