Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
解题:开始进入一个误区,跟循环链表搞混了,其实这个环的开头可以不在head这里,例如下面的链表也是有环的:
最后是看了讨论才找到方法的。设置一个slow指针,每次往前走一步;设置一个fast指针,每次往前走两步;如果在某个时刻这两个指针重合了,说明链表有环。
下面证明有环两个指针一定相遇:
如图,设从head到环的第一个节点的距离为a,从环的第一个节点到两个指针相遇的节点距离为b,环的长度为k。
假设循环执行了t次,那么slow指针走了t步,指向节点(t-a)%k,fast指针走了2*t步,指向节点(2*t-a)%k,则(t-a)%k=(2*t-a)%k;
解出来t = (n2-n1)*k (n1,n2为整数,n2>=n1(fast比slow走的快))
所以相遇时间总是有解的,两个指针一定会相遇。
代码:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 bool hasCycle(ListNode *head) { 12 ListNode* slow = head; 13 ListNode* fast = head; 14 while(fast != NULL && fast->next != NULL){ 15 fast = fast->next->next; 16 slow = slow->next; 17 if(fast == slow) 18 return true; 19 } 20 return false; 21 } 22 };
Java版本代码
1 public class Solution { 2 public boolean hasCycle(ListNode head) { 3 if(head == null) 4 return false; 5 ListNode fast = head.next; 6 ListNode slow = head; 7 while(fast != null && fast.next != null){ 8 if(fast == slow) 9 return true; 10 fast = fast.next.next; 11 slow = slow.next; 12 } 13 return false; 14 } 15 }