因这2道题均不改变链表结构,所以可以不创建新的临时头结点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
if(head==NULL||head->next==NULL)//若只有一个数据结点指向自己head->next!=NULL:head->next!=NULL
return false;
struct ListNode*p1=head->next;//一次走一步
struct ListNode*p2=head->next->next;//一次走两步
while(p2!=NULL&&p2->next!=NULL)
{
if(p1==p2)
return true;
p1=p1->next;//不等接着走
p2=p2->next->next;//p2->next!=NULL
}//为空无环
return false;
}
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
//1.处理判断环
if(head==NULL||head->next==NULL)//没有环;若只有一个数据结点指向自己head->next!=NULL:head->next!=NULL
return false;
//定义快慢2个指针
struct ListNode*p1=head->next;//一次走一步
struct ListNode*p2=head->next->next;//一次走两步
while(p2!=NULL&&p2->next!=NULL)
{
if(p1==p2)//相遇则有环,此时p2一定比p1多走一圈(类似于操场跑圈),即环的长度n;且p2=2*p1
//2(x+y)=x+y+n——>x=n-y;或者2(x+y)=x+y+dn——>x=dn-y=n-y+(d-1)n;2者最终化简结果一样
//x为头结点到入口结点的距离,y为入口结点到相遇结点的距离;所以x+y为从头结点到相遇结点的距离==环的一圈的距离,x+y=n
//慢指针p1走了x+y的距离,快指针比慢指针多走一圈(或者是多走d圈),即p2=x+y+n
//因为p2=2*p1,所以2(x+y)=x+y+n;则x+y=n
break;
p1=p1->next;//不等接着走
p2=p2->next->next;//p2->next!=NULL
}//为空无环
if(p2==NULL||p2->next==NULL)//没有环
return NULL;
//2.计算环的长度
int n=1;//n为环的长度
p1=p1->next;//p1从头开始,走到x+y处即一个n
while(p1!=p2)//p2还在之前相遇的结点处,x+y处
{
n++;
p1=p1->next;
}
//3.入口处的结点距离为x,现在求x
p1=head;//先走的指针
p2=head;//后走的指针
while(n>0)//让p1先走n步,即p1先走一圈,走到x+y处,则n-y=x,即p1再走x步就到入口处x
{
p1=p1->next;
n--;
}//此时p1==x+y,p2==head;2者均再走x步同时到达x处相遇
while(p1!=p2)//现在p1,p2同时走,均一次一步;再次相遇时就是入口处,即p1==p2
{
p1=p1->next;
p2=p2->next;
}
return p1;//相遇的点就是入环点
}