CC环形链表进阶leetcode-T142
目录
【C/C++】环形链表Ⅱ(进阶)(leetcode T142)
我们之前学过环形链表的初级知识,学会了使用快慢指针,学会了判断是否为环形链表,现在题目进行进阶,我们来寻找成环的节点,又要有怎么样的知识呢?
(还不会的读者可以先看 )
核心考点:链表、快慢指针法
题目描述
给定一个链表的头节点
head
,返回链表开始入环的第一个节点。
如果链表无环,则返回
null
。
如果链表中有某个节点,可以通过连续跟踪
next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数
pos
来表示链表尾连接到链表中的位置(
索引从 0 开始
)。如果
pos
是
-1
,则在该链表中没有环。
注意:
pos
不作为参数进行传递
,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
输入: head = [3,2,0,-4], pos = 1
输出: 返回索引为 1 的链表节点
解释: 链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入: head = [1,2], pos = 0
输出: 返回索引为 0 的链表节点
解释: 链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入: head = [1], pos = -1
输出: 返回 null
解释: 链表中没有环。
提示:
- 链表中节点的数目范围在范围
[0, 104]
内 -105 <= Node.val <= 105
pos
的值为-1
或者链表中的一个有效索引
黄金重点:快慢指针分析:
慢指针一步走一个,快指针一步走两个,所以无论何时都有 慢指针走了k,快指针走了2k,快指针之所以能追上慢指针是因为它多走了一圈,所以一圈的长度就是2k-k=k;
现在两个指针相遇了,再让随便一个指针回到起点,两个指针齐步走,按照一步一个的走,可以看到两个指针在 再次相遇时都走了k-m,也就都走到了成环的节点。
代码实现:
struct ListNode* detectCycle(struct ListNode* head)
{
struct ListNode *slow, *fast;
slow = head;
fast = head;
// 🚶♂️快慢指针,寻找相遇点
while (fast != NULL && fast->next != NULL) {
slow = slow->next; // 慢指针每次走一步
fast = fast->next->next; // 快指针每次走两步
if (slow == fast) {
break; // 相遇,说明有环
}
}
// ❌ 如果没有环,直接返回 NULL
if (fast == NULL || fast->next == NULL) {
return NULL;
}
// 🔁 将慢指针放回链表头,快指针保持在相遇点
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
// ✅ 返回入环的第一个节点
return slow;
}
思路分析
本题是典型的“链表找环问题”,可以通过 快慢指针法 来解决。
- 快指针 :每次移动两步
- 慢指针 :每次移动一步
阶段1:检测是否有环
- 如果快慢指针在遍历过程中相遇,说明链表存在环。
- 如果快指针或快指针的下一个节点为空,说明链表无环。
阶段2:寻找环的起点
- 让慢指针回到链表头,快指针保持在相遇的位置。
- 慢指针和快指针同时以每次一步的速度前进。
- 两个指针相遇的节点即为环的入口。