LEETCODE(力扣) 148. 排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
示例 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
进阶:你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
自解
自解大失败,拼尽全力无法战胜超时
//按顺序排到新链表里,超时
struct ListNode dummy;
struct ListNode * s_insert(struct ListNode *newnode)
{
struct ListNode *temp=NULL,*next=NULL,*head=&dummy;
if(head->next==NULL)
{
dummy.next=newnode;
next=newnode->next;
newnode->next=NULL;
return next;
}
while(head->next!=NULL&&head->next->val<newnode->val)
{
head=head->next;
}
temp=head->next;
head->next=newnode;
next=newnode->next;
newnode->next=temp;
return next;
}
struct ListNode* sortList(struct ListNode* head) {
dummy.next=NULL;
while(head!=NULL)
{
head=s_insert(head);
}
return dummy.next;
}
//双指针冒泡排序,超时,实质是对两两交换链表中的节点题加上了判断条件
struct ListNode* sortList(struct ListNode* head) {
if(head==NULL)return head;
struct ListNode dummy;
dummy.next=head;
head=&dummy;
struct ListNode *right=&dummy,*p=NULL;
struct ListNode *temp=NULL,*temp1=NULL;
while(head->next->next!=p)
{
while(right->next->next!=p)
{
if(right->next->val>right->next->next->val)
{
temp=right->next->next->next;
right->next->next->next=right->next;
temp1=right->next->next;
right->next->next=temp;
right->next=temp1;
}
right=right->next;
}
p=right->next;
right=head;
}
return dummy.next;
}
力扣解
1.递归
将链表拆成一个个节点再合并
// 876. 链表的中间结点(快慢指针)
struct ListNode* middleNode(struct ListNode* head) {
struct ListNode* pre = head;
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next) {
pre = slow; // 记录 slow 的前一个节点
slow = slow->next;
fast = fast->next->next;
}
pre->next = NULL; // 断开 slow 的前一个节点和 slow 的连接
return slow;
}
// 21. 合并两个有序链表(双指针)
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
struct ListNode dummy; // 用哨兵节点简化代码逻辑
struct ListNode* cur = &dummy; // cur 指向新链表的末尾
while (list1 && list2) {
if (list1->val < list2->val) {
cur->next = list1; // 把 list1 加到新链表中
list1 = list1->next;
} else { // 注:相等的情况加哪个节点都是可以的
cur->next = list2; // 把 list2 加到新链表中
list2 = list2->next;
}
cur = cur->next;
}
cur->next = list1 ? list1 : list2; // 拼接剩余链表
return dummy.next;
}
struct ListNode* sortList(struct ListNode* head) {
// 如果链表为空或者只有一个节点,无需排序
if (head == NULL || head->next == NULL) {
return head;
}
// 找到中间节点 head2,并断开 head2 与其前一个节点的连接
// 比如 head=[4,2,1,3],那么 middleNode 调用结束后 head=[4,2] head2=[1,3]
struct ListNode* head2 = middleNode(head);
// 分治
head = sortList(head);
head2 = sortList(head2);
// 合并
return mergeTwoLists(head, head2);
}
作者:灵茶山艾府
链接:https://leetcode.cn/problems/sort-list/solutions/2993518/liang-chong-fang-fa-fen-zhi-die-dai-mo-k-caei/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
仿解
看过答案自己写的递归,非常惭愧,合并有序链表明明已经做出来,却又做错,找了好一会错误

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *MiddleFind(struct ListNode *head)//找中间节点
{
struct ListNode *fast=head,*slow=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
struct ListNode *hebing(struct ListNode *list1,struct ListNode *list2)//合并有序节点
{
struct ListNode dummy,*p=&dummy;
while(list1&&list2)
{
if(list1->val<=list2->val)
{
p->next=list1;
p=p->next;
list1=list1->next;
}
else
{
p->next=list2;
p=p->next;
list2=list2->next;
}
}
p->next=list1?list1:list2;
return dummy.next;
}
struct ListNode* sortList(struct ListNode* head) {
struct ListNode *temp=NULL,*temp1=NULL;
if(head==NULL||head->next==NULL)//链表不可切割时停止递归直接返回
{
return head;
}
else
{
temp=MiddleFind(head);//找中间节点
if(temp->next==NULL)//考虑只剩两个节点的特殊情况,此时中间节点是最后一个节点
{
temp1=temp;
head->next=NULL;
}
else
{
temp1=temp->next;
temp->next=NULL;
}
}
head=sortList(head);//递归,此时不需要判断是否为单节点链表,参考上方的返回条件,单节点链表会直接返回自身并且不进行递归
temp1=sortList(temp1);//递归
return hebing(head,temp1);;
}

浙公网安备 33010602011771号