链表作为数据结构中的基础内容,是编程面试中永远绕不开的核心考点。这次我在刷题中碰到了不少常见问题,所以自己写了一个详解:深入解析牛客 101 题单中链表相关的经典题目,解析牛客 101 题单中链表相关的 15 道核心题目,涵盖反转、合并、环检测、排序等高频考点,通过「题目描述 + 思路分析 + 多解法实现 + 复杂度对比 + 易错点」的结构i帮你吃透!!!
附带有本人手写的4k行c源码,帮你彻底吃透链表,文末自取
一、链表基础操作:反转与区间操作
BM1. 反转链表
题目描述:将单链表反转,返回反转后的头节点。
示例:输入1->2->3
,输出3->2->1
。
解法一:迭代法(最优解)
c
struct ListNode* ReverseList(struct ListNode* pHead) {
if (pHead == NULL || pHead->next == NULL) return pHead;
struct ListNode *prev = NULL, *curr = pHead, *next = NULL;
while (curr) {
next = curr->next; // 保存后继节点
curr->next = prev; // 反转指针
prev = curr; // 指针后移
curr = next;
}
return prev;
}
解法二:递归法
c
struct ListNode* reverseRecursive(struct ListNode* head, struct ListNode* prev) {
if (head == NULL) return prev;
struct ListNode* next = head->next;
head->next = prev;
return reverseRecursive(next, head);
}
struct ListNode* ReverseList(struct ListNode* pHead) {
return reverseRecursive(pHead, NULL);
}
复杂度分析:
- 时间:O (n),遍历链表一次
- 空间:迭代法 O (1),递归法 O (n)(栈空间)
易错点:反转时需先保存后继节点,避免断链;空链表或单节点链表需特殊处理。
BM2. 链表内指定区间反转
题目描述:将链表中[m,n]
区间内的节点反转,要求 O (n) 时间和 O (1) 空间。
示例:输入1->2->3->4->5
,m=2, n=4,输出1->4->3->2->5
。
c
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {
if (!head || m >= n) return head;
struct ListNode dummy = {0, head};
struct ListNode *prev = &dummy;
// 定位到区间[m,n]的前驱节点
for (int i = 1; i < m; i++) {
prev = prev->next;
if (!prev) return head;
}
struct ListNode *start = prev->next;
struct ListNode *end = start;
// 定位到区间终点
for (int i = m; i < n; i++) {
end = end->next;
if (!end) return head;
}
struct ListNode *next = end->next;
end->next = NULL;
// 反转区间[start, end]
prev->next = reverse(start); // 调用BM1的反转函数
start->next = next;
return dummy.next;
}
关键点:使用哑节点处理头节点情况,区间反转后需正确连接前驱和后继节点。
二、链表合并与分割
BM4. 合并两个排序链表
题目描述:合并两个递增链表,结果仍递增。
示例:输入1->3->5
和2->4->6
,输出1->2->3->4->5->6
。
解法一:迭代法
c
struct ListNode* Merge(struct ListNode* l1, struct ListNode* l2) {
if (!l1) return l2;
if (!l2) return l1;
struct ListNode dummy = {0, NULL};
struct ListNode *curr = &dummy;
while (l1 && l2) {
if (l1->val <= l2->val) {
curr->next = l1;
l1 = l1->next;
} else {
curr->next = l2;
l2 = l2->next;
}
curr = curr->next;
}
curr->next = l1 ? l1 : l2;
return dummy.next;
}
解法二:递归法
c
运行
struct ListNode* Merge(struct ListNode* l1, struct ListNode* l2) {
if (!l1) return l2;
if (!l2) return l1;
if (l1->val <= l2->val) {
l1->next = Merge(l1->next, l2);
return l1;
} else {
l2->next = Merge(l1, l2->next);
return l2;
}
}
BM5. 合并 k 个排序链表(补充解法)
题目描述:合并 k 个递增链表,结果仍递增。
示例:输入[1->4->5, 1->3->4, 2->6]
,输出1->1->2->3->4->4->5->6
。
解法:优先队列(最小堆)
c
// 定义堆节点
typedef struct {
struct ListNode* node;
} HeapNode;
// 堆操作函数
void swap(HeapNode* a, HeapNode* b) {
HeapNode temp = *a;
*a = *b;
*b = temp;
}
void heapify(HeapNode* heap, int n, int i) {
int smallest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && heap[left].node->val < heap[smallest].node->val)
smallest = left;
if (right < n && heap[right].node->val < heap[smallest].node->val)
smallest = right;
if (smallest != i) {
swap(&heap[i], &heap[smallest]);
heapify(heap, n, smallest);
}
}
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize) {
if (listsSize == 0) return NULL;
// 构建最小堆
HeapNode heap[listsSize];
for (int i = 0; i < listsSize; i++) {
heap[i].node = lists[i];
}
for (int i = listsSize / 2 - 1; i >= 0; i--) {
heapify(heap, listsSize, i);
}
struct ListNode dummy = {0, NULL};
struct ListNode *curr = &dummy;
while (1) {
// 取出堆顶(最小值)
HeapNode top = heap[0];
if (!top.node) break;
curr->next = top.node;
curr = curr->next;
heap[0].node = top.node->next;
// 调整堆
heapify(heap, listsSize, 0);
}
return dummy.next;
}
三、链表环问题:检测与定位
BM6. 判断链表中是否有环
题目描述:用 O (1) 空间判断链表是否有环。
示例:输入1->2->3->2
(环),返回true
。
c
bool hasCycle(struct ListNode* head) {
if (!head || !head->next) return false;
struct ListNode *slow = head, *fast = head->next;
while (slow != fast) {
if (!fast || !fast->next) return false;
slow = slow->next;
fast = fast->next->next;
}
return true;
}
核心原理:快慢指针法,快指针每次走 2 步,慢指针走 1 步,若存在环则必然相遇。
BM7. 链表中环的入口结点
题目描述:找到环的入口节点,若无环返回NULL
。
示例:输入1->2->3->4->3
(环入口为 3),返回值为 3 的节点。
c
运行
struct ListNode* detectCycle(struct ListNode* head) {
if (!head || !head->next) return NULL;
struct ListNode *slow = head, *fast = head;
bool hasCycle = false;
// 找相遇点
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
hasCycle = true;
break;
}
}
if (!hasCycle) return NULL;
// 找入口:慢指针回表头,快慢同速走
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
数学推导:设头到入口为 a,入口到相遇点为 b,环长为 c,则a = (k-1)*c + (c-b)
,即头到入口距离等于相遇点绕环 k-1 圈加剩余距离。
四、链表定位与特殊操作
BM8. 链表中倒数最后 k 个结点
题目描述:找到链表中倒数第 k 个节点。
示例:输入1->2->3->4->5
,k=2,返回 4 的节点。
c
struct ListNode* FindKthToTail(struct ListNode* head, int k) {
if (!head || k <= 0) return NULL;
struct ListNode *fast = head, *slow = head;
// 快指针先走k步
for (int i = 0; i < k; i++) {
if (!fast) return NULL; // k超过链表长度
fast = fast->next;
}
// 快慢同速走
while (fast) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
BM10. 两个链表的第一个公共结点
题目描述:找两个无环链表的第一个公共节点。
示例:输入1->2->6->7
和4->5->6->7
,返回 6 的节点。
c
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2) {
if (!pHead1 || !pHead2) return NULL;
struct ListNode *p1 = pHead1, *p2 = pHead2;
while (p1 != p2) {
p1 = p1 ? p1->next : pHead2;
p2 = p2 ? p2->next : pHead1;
}
return p1;
}
关键思路:双指针遍历总长度相等(m+n),若有公共节点则相遇,若无则同时到 NULL。
五、链表运算与排序
BM11. 链表相加 (二)
题目描述:两链表各节点代表数字一位(逆序存储),求两数之和。
示例:输入9->3->7
和6->3
,输出1->0->0->0
(937+63=1000)。
c
struct ListNode* addInList(struct ListNode* head1, struct ListNode* head2) {
struct ListNode dummy = {0, NULL};
struct ListNode *curr = &dummy;
int carry = 0;
while (head1 || head2 || carry) {
int val1 = head1 ? head1->val : 0;
int val2 = head2 ? head2->val : 0;
int sum = val1 + val2 + carry;
carry = sum / 10;
struct ListNode *newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = sum % 10;
newNode->next = NULL;
curr->next = newNode;
curr = curr->next;
if (head1) head1 = head1->next;
if (head2) head2 = head2->next;
}
return dummy.next;
}
BM12. 单链表的排序
题目描述:对链表排序,要求 O (n log n) 时间和 O (1) 空间。
示例:输入4->2->1->3
,输出1->2->3->4
。
c
// 找链表中点(快慢指针)
struct ListNode* findMiddle(struct ListNode* head) {
if (!head || !head->next) return head;
struct ListNode *slow = head, *fast = head->next;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
// 合并有序链表(同BM4)
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2);
struct ListNode* sortList(struct ListNode* head) {
if (!head || !head->next) return head;
struct ListNode *mid = findMiddle(head);
struct ListNode *rightHead = mid->next;
mid->next = NULL; // 分割链表
struct ListNode *left = sortList(head);
struct ListNode *right = sortList(rightHead);
return mergeTwoLists(left, right);
}
六、链表高级特性判断
BM13. 判断一个链表是否为回文结构
题目描述:判断链表是否是回文(正读反读相同)。
示例:输入1->2->2->1
,返回true
;输入1->2
,返回false
。
解法一:快慢指针 + 栈(O (n) 空间)
c
bool isPalindrome(struct ListNode* head) {
if (!head || !head->next) return true;
struct ListNode *slow = head, *fast = head;
// 快指针到中点,慢指针到前半段末尾
while (fast->next && fast->next->next) {
slow = slow->next;
fast = fast->next->next;
}
// 栈存储前半段
struct ListNode *curr = head;
int stack[10000], top = 0;
while (curr != slow) {
stack[top++] = curr->val;
curr = curr->next;
}
// 比较后半段与栈
curr = slow->next;
while (curr) {
if (top == 0 || stack[--top] != curr->val)
return false;
curr = curr->next;
}
return true;
}
解法二:反转后半段(O (1) 空间)
c
bool isPalindrome(struct ListNode* head) {
if (!head || !head->next) return true;
// 找中点
struct ListNode *slow = head, *fast = head;
while (fast->next && fast->next->next) {
slow = slow->next;
fast = fast->next->next;
}
// 反转后半段
struct ListNode *secondHalf = reverse(slow->next); // 调用BM1的反转函数
slow->next = NULL;
// 比较两段
struct ListNode *p1 = head, *p2 = secondHalf;
bool res = true;
while (p1 && p2) {
if (p1->val != p2->val) {
res = false;
break;
}
p1 = p1->next;
p2 = p2->next;
}
// 恢复链表(可选)
slow->next = reverse(secondHalf);
return res;
}
七、链表元素删除与重排
BM15. 删除有序链表中重复的元素 - I
题目描述:删除有序链表中重复的节点,保留首次出现的节点。
示例:输入1->2->2->3
,输出1->2->3
。
c
struct ListNode* deleteDuplicates(struct ListNode* head) {
if (!head || !head->next) return head;
struct ListNode *curr = head;
while (curr->next) {
if (curr->val == curr->next->val) {
struct ListNode *temp = curr->next;
curr->next = temp->next;
free(temp); // 释放重复节点内存
} else {
curr = curr->next;
}
}
return head;
}
BM16. 删除有序链表中重复的元素 - II
题目描述:删除有序链表中所有重复的节点,只保留不重复的节点。
示例:输入1->2->2->3->3
,输出1
。
c
struct ListNode* deleteDuplicates(struct ListNode* head) {
if (!head || !head->next) return head;
struct ListNode dummy = {0, head};
struct ListNode *prev = &dummy;
struct ListNode *curr = head;
while (curr) {
// 找到不重复的区间
while (curr->next && curr->val == curr->next->val) {
curr = curr->next;
}
if (prev->next == curr) {
// 无重复,指针后移
prev = prev->next;
} else {
// 有重复,跳过所有重复节点
prev->next = curr->next;
}
curr = curr->next;
}
return dummy.next;
}
BM14. 链表的奇偶重排
题目描述:将链表奇数位置节点和偶数位置节点分别排列,奇数在前,偶数在后。
示例:输入1->2->3->4->5
,输出1->3->5->2->4
。
struct ListNode* oddEvenList(struct ListNode* head) {
if (!head || !head->next) return head;
struct ListNode *odd = head;
struct ListNode *even = head->next;
struct ListNode *evenHead = even;
while (even && even->next) {
odd->next = even->next;
odd = odd->next;
even->next = odd->next;
even = even->next;
}
odd->next = evenHead;
return head;
}
我总结的一些技巧:
- 哑节点:处理头节点特殊情况,避免额外条件判断
- 双指针:快慢指针(环检测、中点查找)、前后指针(删除节点)
- 递归:反转、合并、排序等问题可利用递归简化逻辑
- 空间换时间:哈希表记录节点(环检测、公共节点)
四种你可能碰到的陷阱:
- 空链表、单节点链表的边界条件
- 指针操作时的内存泄漏(如删除节点未 free)
- 环问题中快慢指针的初始化顺序
- 区间操作时的指针断链风险
***最终附录,本人的vscode本地手写源码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 定义链表节点结构
struct ListNode {
int val;
struct ListNode *next;
};
// 辅助函数:创建新节点
struct ListNode* createNode(int val) {
struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = val;
newNode->next = NULL;
return newNode;
}
// 辅助函数:打印链表
void printList(struct ListNode* head) {
struct ListNode* curr = head;
while (curr != NULL) {
printf("%d -> ", curr->val);
curr = curr->next;
}
printf("NULL\n");
}
// 辅助函数:释放链表
void freeList(struct ListNode* head) {
struct ListNode* temp;
while (head != NULL) {
temp = head;
head = head->next;
free(temp);
}
}
// BM1: 反转链表
struct ListNode* ReverseList(struct ListNode* pHead) {
struct ListNode* prev = NULL;
struct ListNode* curr = pHead;
struct ListNode* next = NULL;
while (curr != NULL) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
// BM2: 链表内指定区间反转
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {
if (head == NULL || m >= n) return head;
struct ListNode dummy = {0, head};
struct ListNode* prev = &dummy;
// 找到第m-1个节点
for (int i = 1; i < m; i++) {
prev = prev->next;
}
struct ListNode* start = prev->next;
struct ListNode* end = start;
// 找到第n个节点
for (int i = m; i < n; i++) {
end = end->next;
}
struct ListNode* next = end->next;
end->next = NULL;
// 反转区间[m,n]
prev->next = ReverseList(start);
start->next = next;
return dummy.next;
}
// BM4: 合并两个排序的链表
struct ListNode* Merge(struct ListNode* pHead1, struct ListNode* pHead2) {
struct ListNode dummy = {0, NULL};
struct ListNode* tail = &dummy;
while (pHead1 && pHead2) {
if (pHead1->val < pHead2->val) {
tail->next = pHead1;
pHead1 = pHead1->next;
} else {
tail->next = pHead2;
pHead2 = pHead2->next;
}
tail = tail->next;
}
if (pHead1) tail->next = pHead1;
if (pHead2) tail->next = pHead2;
return dummy.next;
}
// BM5: 合并k个已排序的链表
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize) {
if (listsSize == 0) return NULL;
if (listsSize == 1) return lists[0];
int mid = listsSize / 2;
struct ListNode* left = mergeKLists(lists, mid);
struct ListNode* right = mergeKLists(lists + mid, listsSize - mid);
return Merge(left, right);
}
// BM6: 判断链表中是否有环
bool hasCycle(struct ListNode *head) {
if (head == NULL || head->next == NULL) return false;
struct ListNode* slow = head;
struct ListNode* fast = head->next;
while (slow != fast) {
if (fast == NULL || fast->next == NULL) return false;
slow = slow->next;
fast = fast->next->next;
}
return true;
}
// BM7: 链表中环的入口结点
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead) {
if (pHead == NULL || pHead->next == NULL) return NULL;
struct ListNode* slow = pHead;
struct ListNode* fast = pHead;
// 找到相遇点
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) break;
}
if (fast == NULL || fast->next == NULL) return NULL;
// 找到环的入口
slow = pHead;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
// BM8: 链表中倒数最后k个结点
struct ListNode* FindKthToTail(struct ListNode* pHead, int k) {
if (pHead == NULL || k <= 0) return NULL;
struct ListNode* fast = pHead;
struct ListNode* slow = pHead;
// 快指针先走k步
for (int i = 0; i < k; i++) {
if (fast == NULL) return NULL; // k大于链表长度
fast = fast->next;
}
// 快慢指针同时走
while (fast != NULL) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
// BM10: 两个链表的第一个公共结点
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2) {
if (pHead1 == NULL || pHead2 == NULL) return NULL;
struct ListNode* p1 = pHead1;
struct ListNode* p2 = pHead2;
while (p1 != p2) {
p1 = p1 ? p1->next : pHead2;
p2 = p2 ? p2->next : pHead1;
}
return p1;
}
// BM11: 链表相加(二)
struct ListNode* addInList(struct ListNode* head1, struct ListNode* head2) {
// 先反转两个链表
head1 = ReverseList(head1);
head2 = ReverseList(head2);
struct ListNode dummy = {0, NULL};
struct ListNode* tail = &dummy;
int carry = 0;
while (head1 || head2 || carry) {
int sum = carry;
if (head1) {
sum += head1->val;
head1 = head1->next;
}
if (head2) {
sum += head2->val;
head2 = head2->next;
}
carry = sum / 10;
struct ListNode* newNode = createNode(sum % 10);
tail->next = newNode;
tail = tail->next;
}
// 反转结果链表
return ReverseList(dummy.next);
}
// BM12: 单链表的排序
struct ListNode* sortList(struct ListNode* head) {
if (head == NULL || head->next == NULL) return head;
// 快慢指针找到中间节点
struct ListNode* slow = head;
struct ListNode* fast = head->next;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
struct ListNode* mid = slow->next;
slow->next = NULL;
// 递归排序左右两部分
struct ListNode* left = sortList(head);
struct ListNode* right = sortList(mid);
// 合并两个有序链表
return Merge(left, right);
}
// BM13: 判断一个链表是否为回文结构
bool isPalindrome(struct ListNode* head) {
if (head == NULL || head->next == NULL) return true;
// 找到中间节点
struct ListNode* slow = head;
struct ListNode* fast = head->next;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
// 反转后半部分链表
struct ListNode* secondHalf = ReverseList(slow->next);
// 比较前半部分和反转后的后半部分
struct ListNode* p1 = head;
struct ListNode* p2 = secondHalf;
bool result = true;
while (p2 != NULL) {
if (p1->val != p2->val) {
result = false;
break;
}
p1 = p1->next;
p2 = p2->next;
}
// 恢复链表(可选)
slow->next = ReverseList(secondHalf);
return result;
}
// BM14: 链表的奇偶重排
struct ListNode* oddEvenList(struct ListNode* head) {
if (head == NULL || head->next == NULL) return head;
struct ListNode* odd = head;
struct ListNode* even = head->next;
struct ListNode* evenHead = even;
while (even != NULL && even->next != NULL) {
odd->next = even->next;
odd = odd->next;
even->next = odd->next;
even = even->next;
}
odd->next = evenHead;
return head;
}
// BM15: 删除有序链表中重复的元素-I
struct ListNode* deleteDuplicates(struct ListNode* head) {
struct ListNode* curr = head;
while (curr != NULL && curr->next != NULL) {
if (curr->val == curr->next->val) {
struct ListNode* temp = curr->next;
curr->next = temp->next;
free(temp);
} else {
curr = curr->next;
}
}
return head;
}
// BM16: 删除有序链表中重复的元素-II
struct ListNode* deleteDuplicatesII(struct ListNode* head) {
if (head == NULL || head->next == NULL) return head;
struct ListNode dummy = {0, head};
struct ListNode* prev = &dummy;
struct ListNode* curr = head;
while (curr != NULL) {
bool isDuplicate = false;
while (curr->next != NULL && curr->val == curr->next->val) {
isDuplicate = true;
struct ListNode* temp = curr;
curr = curr->next;
free(temp);
}
if (isDuplicate) {
// 删除最后一个重复节点
struct ListNode* temp = curr;
curr = curr->next;
free(temp);
prev->next = curr;
} else {
prev = curr;
curr = curr->next;
}
}
return dummy.next;
}
int main() {
printf("==== 链表算法测试 ====\n");
// 测试BM1: 反转链表
printf("\nBM1: 反转链表\n");
struct ListNode* head1 = createNode(1);
head1->next = createNode(2);
head1->next->next = createNode(3);
head1->next->next->next = createNode(4);
printf("原始链表: ");
printList(head1);
struct ListNode* reversed = ReverseList(head1);
printf("反转后: ");
printList(reversed);
freeList(reversed);
// 测试BM2: 链表内指定区间反转
printf("\nBM2: 链表内指定区间反转\n");
struct ListNode* head2 = createNode(1);
head2->next = createNode(2);
head2->next->next = createNode(3);
head2->next->next->next = createNode(4);
head2->next->next->next->next = createNode(5);
printf("原始链表: ");
printList(head2);
struct ListNode* reversedRange = reverseBetween(head2, 2, 4);
printf("区间[2,4]反转后: ");
printList(reversedRange);
freeList(reversedRange);
// 测试BM4: 合并两个排序的链表
printf("\nBM4: 合并两个排序的链表\n");
struct ListNode* list1 = createNode(1);
list1->next = createNode(3);
list1->next->next = createNode(5);
struct ListNode* list2 = createNode(2);
list2->next = createNode(4);
list2->next->next = createNode(6);
printf("链表1: ");
printList(list1);
printf("链表2: ");
printList(list2);
struct ListNode* merged = Merge(list1, list2);
printf("合并后: ");
printList(merged);
freeList(merged);
// 测试BM5: 合并k个已排序的链表
printf("\nBM5: 合并k个已排序的链表\n");
struct ListNode* lists[3];
lists[0] = createNode(1);
lists[0]->next = createNode(4);
lists[0]->next->next = createNode(5);
lists[1] = createNode(1);
lists[1]->next = createNode(3);
lists[1]->next->next = createNode(4);
lists[2] = createNode(2);
lists[2]->next = createNode(6);
printf("链表1: ");
printList(lists[0]);
printf("链表2: ");
printList(lists[1]);
printf("链表3: ");
printList(lists[2]);
struct ListNode* mergedK = mergeKLists(lists, 3);
printf("合并后: ");
printList(mergedK);
freeList(mergedK);
// 测试BM6: 判断链表中是否有环
printf("\nBM6: 判断链表中是否有环\n");
struct ListNode* loopList = createNode(1);
loopList->next = createNode(2);
loopList->next->next = createNode(3);
loopList->next->next->next = createNode(4);
loopList->next->next->next->next = loopList->next; // 创建环
printf("链表是否有环: %s\n", hasCycle(loopList) ? "是" : "否");
// 注意:有环链表不能直接释放,需先破环
// 测试BM7: 链表中环的入口结点
printf("\nBM7: 链表中环的入口结点\n");
struct ListNode* loopList2 = createNode(1);
loopList2->next = createNode(2);
loopList2->next->next = createNode(3);
loopList2->next->next->next = createNode(4);
loopList2->next->next->next->next = loopList2->next; // 环入口为2
struct ListNode* loopEntry = EntryNodeOfLoop(loopList2);
printf("环的入口值: %d\n", loopEntry ? loopEntry->val : -1);
// 测试BM8: 链表中倒数最后k个结点
printf("\nBM8: 链表中倒数最后k个结点\n");
struct ListNode* list8 = createNode(1);
list8->next = createNode(2);
list8->next->next = createNode(3);
list8->next->next->next = createNode(4);
list8->next->next->next->next = createNode(5);
printf("原始链表: ");
printList(list8);
struct ListNode* kthNode = FindKthToTail(list8, 2);
printf("倒数第2个结点值: %d\n", kthNode->val);
freeList(list8);
// 测试BM10: 两个链表的第一个公共结点
printf("\nBM10: 两个链表的第一个公共结点\n");
struct ListNode* commonNode = createNode(6);
commonNode->next = createNode(7);
struct ListNode* list10a = createNode(1);
list10a->next = createNode(2);
list10a->next->next = commonNode;
struct ListNode* list10b = createNode(4);
list10b->next = createNode(5);
list10b->next->next = commonNode;
printf("链表1: ");
printList(list10a);
printf("链表2: ");
printList(list10b);
struct ListNode* common = FindFirstCommonNode(list10a, list10b);
printf("第一个公共结点值: %d\n", common->val);
// 测试BM11: 链表相加(二)
printf("\nBM11: 链表相加(二)\n");
struct ListNode* add1 = createNode(9);
add1->next = createNode(3);
add1->next->next = createNode(7);
struct ListNode* add2 = createNode(6);
add2->next = createNode(3);
printf("链表1: ");
printList(add1);
printf("链表2: ");
printList(add2);
struct ListNode* sum = addInList(add1, add2);
printf("相加后: ");
printList(sum);
freeList(sum);
// 测试BM12: 单链表的排序
printf("\nBM12: 单链表的排序\n");
struct ListNode* unsorted = createNode(4);
unsorted->next = createNode(2);
unsorted->next->next = createNode(1);
unsorted->next->next->next = createNode(3);
printf("原始链表: ");
printList(unsorted);
struct ListNode* sorted = sortList(unsorted);
printf("排序后: ");
printList(sorted);
freeList(sorted);
// 测试BM13: 判断一个链表是否为回文结构
printf("\nBM13: 判断一个链表是否为回文结构\n");
struct ListNode* palindrome = createNode(1);
palindrome->next = createNode(2);
palindrome->next->next = createNode(2);
palindrome->next->next->next = createNode(1);
printf("链表: ");
printList(palindrome);
printf("是否为回文: %s\n", isPalindrome(palindrome) ? "是" : "否");
freeList(palindrome);
// 测试BM14: 链表的奇偶重排
printf("\nBM14: 链表的奇偶重排\n");
struct ListNode* list14 = createNode(1);
list14->next = createNode(2);
list14->next->next = createNode(3);
list14->next->next->next = createNode(4);
list14->next->next->next->next = createNode(5);
printf("原始链表: ");
printList(list14);
struct ListNode* oddEven = oddEvenList(list14);
printf("奇偶重排后: ");
printList(oddEven);
freeList(oddEven);
// 测试BM15: 删除有序链表中重复的元素-I
printf("\nBM15: 删除有序链表中重复的元素-I\n");
struct ListNode* duplicates1 = createNode(1);
duplicates1->next = createNode(2);
duplicates1->next->next = createNode(2);
duplicates1->next->next->next = createNode(3);
printf("原始链表: ");
printList(duplicates1);
struct ListNode* cleaned1 = deleteDuplicates(duplicates1);
printf("删除重复后: ");
printList(cleaned1);
freeList(cleaned1);
// 测试BM16: 删除有序链表中重复的元素-II
printf("\nBM16: 删除有序链表中重复的元素-II\n");
struct ListNode* duplicates2 = createNode(1);
duplicates2->next = createNode(2);
duplicates2->next->next = createNode(2);
duplicates2->next->next->next = createNode(3);
duplicates2->next->next->next->next = createNode(3);
printf("原始链表: ");
printList(duplicates2);
struct ListNode* cleaned2 = deleteDuplicatesII(duplicates2);
printf("删除所有重复后: ");
printList(cleaned2);
freeList(cleaned2);
return 0;
}