题目来源:
https://leetcode-cn.com/problems/linked-list-cycle-ii/description/
题目描述:
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
说明:不允许修改给定的链表。
进阶:
你是否可以不用额外空间解决此题?
该题是上一篇博客的升级版。https://blog.csdn.net/qq_39241239/article/details/84309615
解法一:
- 首先判断是否存在环,利用快慢指针法,从头节点开始快指针每次走两步,慢指针每次走一步,如果存在环则两指针必定会相遇,如果没有再次相遇则不存在环
- 然后找到环中节点的个数,此时快指针已经处在环内,所以让其每次向前走一步,记录再次和慢指针相遇时走的步数即为环中节点个数
- 找环入口节点时还是利用快慢指针,从头节点开始先让快指针走环中节点个数的步数,然后快慢指针同时向前移动,这样相遇时快指针恰好比满指针多走了一个环的长度,即指向了环入口节点
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head == NULL) return NULL;
ListNode *fast = head, *slow = head;
int len = 0;
while(fast->next && fast->next->next){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
len = 1;
break;
}
}
if(len == 0) return NULL;
while(fast->next != slow){
fast = fast->next;
len++;
}
fast = head;
slow = head;
while(len-- > 0){
fast = fast->next;
}
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
};
解法二:
我们只看有环的情况,就是head到第一次两个指针fast slow相遇的节点的距离,设为a+b,其中a是head到入环点的距离,b是入环点到相遇点的距离,设环的长度为r,c是相遇点到入环点的距离,那么c=r-b;所以有,2(a+b)=a+nr+b(a+b是慢指针距离,乘2就是fast指针),快指针肯定在环里饶了那么n圈,n大于等于1,上式化简:a=(n-1)r+c;从这个式子我们发现,只要再来一个指针从head开始,同时slow指针继续走,就会在入环点相遇。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head==NULL||head->next == NULL)
return NULL;
ListNode* slow = head;
ListNode* fast = head;
while(fast!=NULL&&fast->next!=NULL){
slow = slow->next;
fast = fast->next->next;
if(slow==fast){
slow = head;
while(slow!=fast){
slow = slow->next;
fast = fast->next;
}
return slow;
}
}
return NULL;
}
};