算法题——单链表的归并排序
题目:单链表的归并排序,返回排序后的链表。传统的归并都是数组,可以随机访问元素,链表则需要顺序遍历找中间结点。
思路:
设置两个指针,一个步长为1, 一个步长为2,当快指针到达尾结点时,慢指针指向中间结点,时间复杂度为O(N);
平分为左链表L1和右链表L2,递归分裂,直到链表为空或者只有一个结点;
将链表L2的每个结点插入到链表L1中,时间复杂度为O(m+n),m、n分别为两条链表的长度。
画出递归树,可知总的时间复杂度为O(N * lgN)。
代码:
合并两个有序的链表:
1 struct ListNode
2 {
3 int value;
4 ListNode *next;
5 ListNode(int v): value(v), next(NULL)
6 {
7 }
8 };
9
10 ListNode *mergeSortedList(ListNode *L1, ListNode *L2)
11 {
12 ListNode dummy(-1), *p1 = &dummy, *p2 = L2; //L1的辅助头结点dummy,因为可能在头部插入
13 dummy.next = L1;
14 while(p1->next != NULL && p2 != NULL) //停止条件,也包括了判断两个链表是否为空
15 {
16 if(p1->next->value >= p2->value)
17 {
18 L2 = p2->next;
19 p2->next = p1->next;
20 p1->next = p2;
21 p1 = p2;
22 p2 = L2;
23 }
24 else
25 {
26 p1 = p1->next;
27 }
28 }
29 if(p1->next == NULL) //L2可能还有未处理的结点,直接加在L1尾部即可
30 {
31 p1->next = p2;
32 }
33
34 return dummy.next;
35 }
单链表的归并排序:
1 ListNode *listMergeSort(ListNode *head)
2 {
3 if(head == NULL || head->next == NULL) //链表为空,或者只有一个结点,直接返回
4 return head;
5
6 ListNode *slow = head, *fast = head;
7 while(fast->next != NULL && fast->next->next != NULL)
8 {
9 fast = fast->next->next;
10 slow = slow->next;
11 }
12
13 ListNode *leftHead = head, *rightHead = slow->next;
14 slow->next = NULL; //需要把左半链表的尾结点的next赋空值,所以用一个变量来记录右半链表的头
15
16 leftHead = listMergeSort(leftHead);
17 rightHead = listMergeSort(rightHead);
18
19 return mergeSortedList(leftHead, rightHead);
20 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南