142. 环形链表 II

题目

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos-1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表。

进阶:

  • 你是否可以使用 O(1) 空间解决此题?

示例 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 或者链表中的一个有效索引

思路

就是暴力
1.先通过两个从头开始的指针,一个一次走一步,一个一次走两步,看两者能不能相遇,以此来确定有没有环,如果没有环直接返回NULL,有环则记录下两个指针相等的位置n1.
2.如果有环,那么环的头节点一定在head到n1之间,那么只需要再head和n1之间便利,从head往后一个一个开始,看看循环1~2圈只能能不能回到起始节点,如果可以那么证明事头节点,如果不行就往后。直到找到。

代码

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
/**
* 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) return head;
ListNode* n1,*n2;
n1=head;
n2=head->next;
// if(n1==NULL||n2==NULL||n2->next==NULL) return NULL;
while(n1!=n2){
// printf("n1:%d n2:%d\n",n1->val,n2->val);
if(n2==NULL||n2->next==NULL) return NULL;
n2=n2->next->next;
n1=n1->next;
};
//再head和n1之间存在环,从一个节点开始,到n1结束
ListNode* h=head;
//h肯定在h~n1之间,看h到n1之前的节点是不是一样,前面有就在前面,前面没有就是n1
while(h!=n1){
bool finded=false;
ListNode* ch=h->next;
while(ch!=h){
if(ch==n1){
if(finded){
break;
}else{
finded=true;
}
}
ch=ch->next;
}
if(ch==h) return h;
else h=h->next;
}
return h;
}
};