题目描述:给定两个可能有环也可能无环的单链表,头结点head1和head2,请实现一个函数,如果两个链表相交,请返回相交的第一个结点,如果不相交,返回null

解决代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <stdio.h>
#include <stdbool.h>

struct ListNode {
int val;
struct ListNode* next;
};

struct ListNode* detectCycle(struct ListNode* head) {
if (head == NULL || head->next == NULL) {
return NULL; // 链表为空或只有一个节点,不可能有环
}

struct ListNode* slow = head;
struct ListNode* fast = head;

// 快慢指针相遇的检测
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 = head;

// 在相遇点和头节点分别设置一个新指针,每次移动一步,它们相遇的节点即为环的入口
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}

return slow;
}

// 示例用法
int main() {
struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
head->val = 1;
head->next = (struct ListNode*)malloc(sizeof(struct ListNode));
head->next->val = 2;
head->next->next = (struct ListNode*)malloc(sizeof(struct ListNode));
head->next->next->val = 3;
head->next->next->next = head->next; // 创建一个环

struct ListNode* result = detectCycle(head);

if (result != NULL) {
printf("The linked list has a cycle, and the entrance to the cycle is at node with value %d.\n", result->val);
} else {
printf("The linked list does not have a cycle.\n");
}

// 释放内存
while (head != NULL) {
struct ListNode* temp = head;
head = head->next;
free(temp);
}

return 0;
}