Linked List Cycle--LeetCode

题目:

Given a linked list, determine if it has a cycle in it.

Follow up:

Can you solve it without using extra space?

思路:上述题目中所说的不需要额外空间是指非常数的额外空间。

当然,从最基本的考虑,可以使用hashset来存储一个链表的所有节点,如果发现节点一样,那么说明这个链表存在环。只不过这样是存在额外空间的。

如果不使用额外空间,那么可以使用两个指针来遍历整个链表,慢指针就是一步一步往前走,快指针就是每次走两步,这样比慢指针要快一些,如果发现慢指针和快指针相遇,那么说明这个链表存在环。

介绍完方法,剩下的主要就是数学了,假设两个指针walker和runner,walker一倍速移动,runner两倍速移动。有一个链表,假设他在cycle开始前有a个结点,cycle长度是c,而我们相遇的点在cycle开始后b个结点。那么想要两个指针相遇,意味着要满足以下条件:(1) a+b+mc=s; (2) a+b+nc=2s; 其中s是指针走过的步数,m和n是两个常数。这里面还有一个隐含的条件,就是s必须大于等于a,否则还没走到cycle里面,两个指针不可能相遇。假设k是最小的整数使得a<=kc,也就是说(3) a<=kc<=a+c。接下来我们取m=0, n=k,用(2)-(1)可以得到s=kc以及a+b=kc。由此我们可以知道,只要取b=kc-a(由(3)可以知道b不会超过c),那么(1)和(2)便可以同时满足,使得两个指针相遇在离cycle起始点b的结点上。
因为s=kc<=a+c=n,其中n是链表的长度,所以走过的步数小于等于n,时间复杂度是O(n)。并且不需要额外空间,空间复杂度O(1)。代码如下:

//使用快慢指针来判断一个链表中是否存在环 
bool isCycle(List* list)
{
	List* fast=list;
	List* slow=list;
	while(fast != NULL && fast->next != NULL)
	{
		slow = slow->next;
		fast = fast->next->next;
		if(slow == fast)
			return true;
	}
	return false;
} 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值