LeetCode 148. 排序链表
在一般情况下,我们使用数组实现的快速排序,总是选取首元节点作枢纽(privot),并通过与枢纽的值进行比较,使用“填坑-挖坑法”将枢纽放到合适的位置上。
但是链表无法这么做,链表不支持随机访问。
但是,我们只要能实现前面的值都比枢纽小,后面的值都比枢纽大,就算是找到适合的位置了。由于链表十分适合任意位置的插入删除。
因而可以考虑以下思路:
我们取出链表的首元节点作为枢纽,顺序遍历链表,使得小于首元节点的值归类与一个链表。相应的,使得大于首元节点的值归类于另一个链表。
将链表分裂成大小链表两块,最后再合并起来。
此处使用快排实现只是锻炼思路,面对题目中极端的测试用例,快排将会退化到O( n 2 n^2 n2)
快排的稳定化基本上也是基于上述的思路,快排实现的稳定与否取决于partition部分的元素排位是根据交换还是插入
/*删除next元素,并返回*/
ListNode* delNext(ListNode* lst) {
if (lst == nullptr || lst->next == nullptr) return nullptr;
ListNode* res = lst->next;
lst->next = lst->next->next;
return res;
}
/*添加到表尾*/
void appendTail(ListNode* head, ListNode** rear, ListNode* n) {
if (*rear == nullptr) {
*rear = head->next = n;
}else {
(*rear)->next = n;
(*rear) = (*rear)->next;
}
}
bool isEmpty(ListNode* head) {
return head->next == nullptr;
}
ListNode* quickSort(ListNode* head, ListNode* tail) {
// 空链表或者只有一个节点
if (head == tail || head->next == tail) return head;
ListNode low(-1, nullptr); // low lst 临时保存小于privot的节点
ListNode* p_low = &low; // low lst 头节点
ListNode* p_low_tail = nullptr;// low lst 尾指针
ListNode up(-1, nullptr);
ListNode* p_up = &up; // max lst
ListNode* p_up_tail = nullptr; // max lst tail
ListNode* privot = delNext(head);
ListNode* prev = head;
while (prev->next != tail) {
ListNode* del = delNext(prev);
if (del->val < privot->val)
appendTail(p_low, &p_low_tail, del);
else
appendTail(p_up, &p_up_tail, del);
}
if (isEmpty(p_low)) {
head->next = privot;
}
else{
head->next = p_low->next;
p_low_tail->next = privot;
}
if (isEmpty(p_up)) {
privot->next = tail;
}
else {
privot->next = p_up->next;
p_up_tail->next = tail;
}
quickSort(head, privot);
quickSort(privot, tail);
return head->next;
}
/* 此处head形参不包含头节点 */
ListNode* sortList(ListNode* head) {
if (!head) return head;
ListNode newHead(-1, head);
return quickSort(&newHead, nullptr);
}
ListNode* getMidNode(ListNode* head, ListNode* tail) {
ListNode* s = head;
ListNode* f = head->next == tail ? tail : head->next->next;
while (f != tail) {
s = s->next;
f = f->next == tail ? tail : f->next->next;
}
return s->next;
}
void append(ListNode** head, ListNode** rear, ListNode* n) {
if (*head == nullptr) {
*head = n;
*rear = n;
return;
}
(*rear)->next = n;
(*rear) = (*rear)->next;
}
ListNode* merge(ListNode* lst1, ListNode* lst2) {
if (!lst1 && !lst2) return nullptr;
ListNode* head = nullptr;
ListNode* tail = nullptr;
while (lst1 && lst2) {
if (lst1->val < lst2->val) {
append(&head, &tail, lst1);
lst1 = lst1->next;
}
else {
append(&head, &tail, lst2);
lst2 = lst2->next;
}
}
if (lst1) {
append(&head, &tail, lst1);
}
if (lst2) {
append(&head, &tail, lst2);
}
return head;
}
/* 此处head 无头节点 */
ListNode* mergeSort(ListNode* head, ListNode* tail) {
if (head == nullptr) return head;
/*防止出现链表尾节点非null*/
if (head == tail || head->next == tail) {
head->next = nullptr;
return head;
}
ListNode* mid = getMidNode(head, tail);
ListNode* l = mergeSort(head, mid);
ListNode* r = mergeSort(mid, tail);
return merge(l, r);
}
ListNode* sortList(ListNode* head) {
if (!head) return head;
return mergeSort(head, nullptr);
}
第二个版本:
class Solution {
public:
std::pair<ListNode*, ListNode*>
spliceList(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head->next ? head->next->next : nullptr;
while (fast != nullptr) {
slow = slow->next;
fast = fast->next ? fast->next->next : nullptr;
}
ListNode* lst1 = head;
ListNode* lst2 = slow->next;
slow->next = nullptr;
return { lst1, lst2 };
}
void append(ListNode*& list, ListNode*& rear, ListNode* n) {
if (list == nullptr) {
list = n;
rear = n;
}
else {
rear->next = n;
rear = n;
}
}
ListNode* merage(ListNode* lst1, ListNode* lst2) {
ListNode* head = nullptr, * rear = nullptr;
while (lst1 && lst2) {
if (lst1->val < lst2->val) {
append(head, rear, lst1);
lst1 = lst1->next;
}
else {
append(head, rear, lst2);
lst2 = lst2->next;
}
}
if (lst1) append(head, rear, lst1);
if (lst2) append(head, rear, lst2);
return head;
}
ListNode* mergeSort(ListNode* head) {
if (head == nullptr || head->next == nullptr) return head;
auto lsts = spliceList(head);
ListNode* l = mergeSort(lsts.first);
ListNode* r = mergeSort(lsts.second);
return merage(l, r);
}
ListNode* sortList(ListNode* head) {
if (!head) return head;
return mergeSort(head);
}
};