Linked List Cycle--LeetCode

来源:互联网 发布:万合天宜 知乎 编辑:程序博客网 时间:2024/06/05 11:28

题目:

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