主要思路
哈希表法:
同 LeetCode 1#41环形链表 当集合中出现第一个元素数量不为0的即为入环的第一个结点,返回即可
快慢指针法:
b为环中上半部分距离,c为环中下半部分距离
假设快慢指针相遇时快指针已在环里面转了n圈
当快慢指针相遇时,快指针已走的距离为
a + n(b+c) + b = a + (n+1)b + nc
慢指针走的距离为:a + b
快指针的距离始终为慢指针的2倍
a + (n+1)b + nc =2a +2b
化简得: a = (n-1)b + nc = (n-1)(b+c) + c
也就是说当快慢指针相遇时,慢指针在走c步的距离正好等于a的长度,也就是到达入环的第一个结点
当快慢指针相遇时,我们在设置一个指针ptr指向头结点,和慢指针一起走,当他们相遇时,此时的结点即为所求
//给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
struct ListNode
{
int val;
ListNode *next;
ListNode():val(0),next(nullptr){}
ListNode(int x):val(x),next(nullptr){}
ListNode(int x,ListNode *next):val(x),next(next){}
};
//哈希表
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head==nullptr||head->next == nullptr)return nullptr;
set<ListNode *> sl;
ListNode *cur = head;
while(cur) {
if(sl.count(cur)) {
return cur;
}
sl.insert(cur);
cur = cur->next;
}
return nullptr;
}
};
//快慢指针 + 计算
/*
b
// - - -
/* - -
a - -
------------------- -
- -
- - -
c
*/
/*
b为上半圈距离,c为下半圈距离
假设链表形状如上图,快慢指针相遇时快指针已在环里面转了n圈
当快慢指针相遇时,快指针已走的距离为
a + n(b+c) + b = a + (n+1)b + nc
慢指针走的距离为:a + b
快指针的距离始终为慢指针的2倍
a + (n+1)b + nc =2a +2b
化简得: a = (n-1)b + nc = (n-1)(b+c) + c
也就是说当快慢指针相遇时,慢指针在走c步的距离正好等于a的长度,也就是到达入环的第一个结点
当快慢指针相遇时,我们在设置一个指针ptr指向头结点,和慢指针一起走,当他们相遇时,此时的结点即为所求
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head==nullptr||head->next == nullptr)return nullptr;
ListNode *slow = head;
ListNode *fast = head;
while(fast!=nullptr) {
slow = slow->next;
if(fast->next==nullptr) {
return nullptr;
}
fast = fast->next->next;
if(fast==slow) {
ListNode *ptr = head;
while(ptr!=slow) {
slow = slow -> next;
ptr = ptr->next;
}
return ptr;
}
}
return nullptr;
}
};