快慢指针判断单链表中是否存在环,存在返回环的起点的值

没有头指针的单链表

/*示例结点
struct ListNode{
          int val;
          struct ListNode *next;
          ListNode(int x):val(x),next(NULL){}
};
*/

具体步骤:

1、快指针(p_swift)、慢指针(p_slow)同时指向首元结点。慢指针一次走一步,快指针一次走两步。

2、当快指针(p_swift)指向NULL时,若快慢指针从没有“碰过面”,则该单链表没有环。

3、当快慢指针“碰面”时。将慢指针重新指向首元结点,快慢指针同时一次一步,当它们再次相遇时,指向的结点就是环的起点。


数学推理:

1、当慢指针走到位置K时(即走到环的起点),快指针走到位置[K+K%(N-K)]。

2、设慢指针再走b步(即快指针再走2b步),快慢指针相遇。设此时相遇的位置为X。

3、得到 X=K+b%(N-K)

X=K+K%(N-K)+2b%(N-K)。

联立二式得:(K+b)=i*(N-K); i为整数。

4、所以X=K+b%(N-K),可以化为X=K+[i*(N-K)-K]%(N-K);

5、慢指针重新指向首元结点,需要走K步到达位置K。X再走K步后位置变为K+[i*(N-K)-K]%(N-K)+K%(N-K)=K。

此时快慢指针正好在环的起点相遇。

同理,也可知当慢指针指向首元结点后,快慢指针再次相遇的位置就是环的起点。


下面请看代码:(没有环返回-1,有环返回环的起点的值)

int judge(ListNode *head){
	ListNode *p_slow,*q_swift;
	p_slow=q_swift=head;
	if(head->next==NULL)
		return -1;
	p_slow=p_slow->next;
	q_swift=q_swift->next->next;
	while(q_swift&&q_swift->next)
	{
		if(p_slow==q_swift)
		{
			q_swift=head;
			while(q_swift!=p_slow)
			{
				q_swift=q_swift->next;
				p_slow=p_slow->next;
			}
			return p_slow->val;
		}
		else
		{
			p_slow=p_slow->next;
			q_swift=q_swift->next->next;
		}
	}
	return -1;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值