【单链表练习】 - 判断链表中是否有环

题目描述

描述
给定一个链表,判断链表中是否有环。
在这里插入图片描述


解题分析:

思路:
两个指针指向同一个头结点,一个指针为slow,每次走一步,一个指针为fast,每次走两步。
快指针先进入环,当快指针在环中走完N圈后,慢指针刚进入环,快指针开始追赶进入环的慢指针。
当快指针的地址等于慢指针的地址时,即他们相遇了,说明链表为环形链表
如果不带环,fast就会走到空。如果带环,fast就会在环里面追上slow。

代码实现:

struct ListNode
{
	int val;
	struct ListNode* next;
};
int hasCycle(struct ListNode* head)
{
	struct ListNode* slow = head;
	struct ListNode* fast = head;
	while (fast != NULL && fast->next != NULL)//循环条件:可能不为环,此时奇数个结点fast为空结束,偶数个结点fast->next为空结束
	{
		slow = slow->next;
		fast = fast->next->next;
		if (slow == fast)
		{
			return 1;
		}
	}
	return 0;
}

思考:
面试官:请证明快指针是如何追上慢指针的?
如果慢指针一次走1步,快指针一次走3步呢?4步呢?n步?
注意:当进环后,都是fast追慢指针。
1、第一种情况:慢指针走1步,快指针走2步(这种情况慢指针只可能最多走一圈)
假设慢指针进入环以后,fast和slow之间的距离为X
当他们同时每走一次,他们之间的距离缩小1,即X+1-2=X-1
当他们一直走下去,X-1、X-2、X-3…当X = 0时,二者一定会相遇。
2、第二种情况:慢指针走一步,快指针走3步
假设慢指针进入环以后,fast和slow之间的距离为X(这种情况慢指针可能走多圈,可能相遇)
当他们同时每走一次,他们之间的距离缩小2,即X+1-3=X-2
当他们一直走下去,X-2、X-4、X-6…
此时如果x为偶数(2的倍数)时,就会相遇。如果X为奇数(不是2的倍数)时,当X = -1时,二者就错开了。
下一次追赶,二者相差C-1,C为环的长度。如果C-1是奇数,那么之后永远追不上。如果是偶数,就可以追上。
也就是,N=C-1时,每次缩小2,如果极端情况下(死循环)每次差距都是奇数,就会一直错过,导致死循环。
3、第三种情况:慢指针走一步,快指针走4步
假设慢指针进入环以后,fast和slow之间的距离为X(这种情况慢指针可能最多走一圈,可能相遇)
当他们同时每走一次,他们之间的距离缩小3,即X+1-4=X-3
当他们一直走下去,X-3、X-6、X-9…
此时如果x为(3的倍数)时,就会相遇。如果X为(不是3的倍数)时,当X = -2时,二者就错开了。
下一次追赶,二者相差C-1或C-2,C为环的长度。如果C-1或C-2不是3的倍数,那么之后永远追不上。如果是3的倍数,可以相遇。
也就是,N=C-1或C-2时,每次缩小2,如果极端情况下(死循环)每次差距都不是3的倍数,就会一直错过,导致死循环。
因此:当慢指针一次走一步,快指针一次走N步,类似的道理。
那么如何求入口点呢?返回入口点的指针。详见这一篇文章“【单链表练习】 - 求环形链表的入口点”。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值