leetcode 链接:环路检测
《程序员面试代码指南》by 左程云 中相似题目:★★★★两个单链表相交的一系列问题
题目
给定一个链表,如果它是有环链表,实现一个算法返回环路的开头节点。
有环链表的定义:在链表中某个节点的 next 元素指向在它前面出现过的节点,则表明该链表存在环路
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。
解答 & 代码
算法流程:
- 如果链表为空 或 只有一个节点且该节点的
next
指向 NULL,则链表无环,直接返回 NULL - 设置一个快指针和一个慢指针。初始慢指针指向第一个节点,快指针指向第二个节点。遍历链表
- 慢指针一次走一步,快指针一次走两步
- 如果链表无环,则快指针的 next 或 next->next 最终会指向
nullptr
,退出循环,返回 NULL,代表无环 - 如果链表有环,则快指针和慢指针会相遇,退出循环
- 令快指针回到头节点,接着快慢指针都一次走一步,两者再次相遇的节点就是入环节点
理论解释:
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head == NULL || head->next == NULL)
return NULL;
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* fast = dummyHead->next->next;
ListNode* slow = dummyHead->next;
while(fast != slow && fast->next != NULL && fast->next->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
if(fast != slow)
return NULL;
fast = dummyHead;
while(fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return fast;
}
};
执行结果:
执行结果:通过
执行用时:8 ms, 在所有 C++ 提交中击败了 91.87% 的用户
内存消耗:7.4 MB, 在所有 C++ 提交中击败了 78.03% 的用户