题目描述
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
题目分析
根据题意,可以使用归并排序来对链表进行排序。归并排序是基于分治的思想,比较容易实现的就是自顶向下的递归方式来实现。
- 先找出链表的中点,可以使用快慢指针来完成;
- 然后以中点为界,将链表拆分成两个子链表分别进行排序;
- 将两个排序后的子链表进行合并,得到完整的排序后的链表;
- 使用递归方式实现上述操作,递归终止条件为链表为空或者链表只包含一个节点。
Code
class Solution {
public:
ListNode* sortList(ListNode* head) {
return sortList(head, nullptr);
}
private:
ListNode* sortList(ListNode* head, ListNode* tail) {
if (nullptr == head) {
return head;
}
if (head->next == tail) {
head->next = nullptr;
return head;
}
ListNode* slow = head, *fast = head;
while (fast != tail) {
slow = slow->next;
fast = fast->next;
if (fast != tail) {
fast = fast->next;
}
}
return merge(sortList(head, slow), sortList(slow, tail));
}
ListNode* merge(ListNode* head1, ListNode* head2) {
ListNode dummy;
ListNode* temp = &dummy, *l1 = head1, *l2 = head2;
while (nullptr != l1 && nullptr != l2) {
if (l1->val <= l2->val) {
temp->next = l1;
l1 = l1->next;
} else {
temp->next = l2;
l2 = l2->next;
}
temp = temp->next;
}
temp->next = l1 ? l1 : l2;
return dummy.next;
}
};