链表排序的问题,要求时间复杂度为O(nlogn),空间复杂度为常数。
比如:
Input: 4->2->1->3
Output: 1->2->3->4
这道题的思路是用归并排序,我们先看代码:
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (!head || !(head->next))
return head;
auto pFast = head, pSlow = head;
ListNode* pPrev = nullptr;
while (pFast && pFast->next) {
pPrev = pSlow;
pSlow = pSlow->next;
pFast = pFast->next->next;
}
pPrev->next = nullptr;
auto p1 = sortList(head);
auto p2 = sortList(pSlow);
return merge(p1, p2);
}
private:
ListNode* merge(ListNode* head1, ListNode* head2) {
if (!head1)
return head2;
if (!head2)
return head1;
if (head1->val < head2->val) {
head1->next = merge(head1->next, head2);
return head1;
}
else {
head2->next = merge(head1, head2->next);
return head2;
}
}
};
这里有几个有意思的点:
1.又是使用一快一慢两个指针,来找到链表的中间位置。
2.可以将pPrev的next设为null,将原来的长链表切断为两个分别以head和pSlow开头的短链表。
3.merge()函数,我觉得我这样用递归来写还是比较自然优雅的。
所以这道题的两个函数都用到了递归,它们都是与自己递归,互不相干。