Given a linked list, determine if it has a cycle in it.
Follow up: Can you solve it without using extra space?
摘自剑指offer:当用一个指针遍历链表不能解决问题的时候,可以尝试用两个指针来遍历链表,可以让一个指针遍历的速度快一些,或者让他先在链表上走若干步。
相关的题目有:
求链表的中间节点,
判断一个单向链表是否形成了环形结构
判断有环链表的环的入口节点
一次遍历求链表的倒数第K个节点
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
判断是否有环代码如下:
public boolean hasCycle(ListNode head) { ListNode slow = head; ListNode fast = head; if(head==null||head.next==null){ return false; } while(slow.next!=null&&fast.next!=null&&fast.next.next!=null){ slow = slow.next; fast = fast.next.next; if(slow==fast){ return true; } } return false; }
判断环的入口点:
和剑指offer的第56题一样,也是用了两个指针,第一个指针从head向前走了环中节点个数步,第二个指针指向head,两个指针以同样的速度前进,知道两个指针相遇即为环入口点。
首先必须知道环中节点的个数,可以利用上题,找到两个指针相遇的地方即环中某个节点,然后开始计数。
代码如下:
public ListNode detectCycle(ListNode head) { ListNode meetNode = meet(head); int nodeLoop = 1; ListNode node1 = meetNode; if(node1==null){ return null; } while(node1.next!=meetNode){ node1 = node1.next; nodeLoop = nodeLoop + 1; } ListNode node2 = head; for(int i = 0;i<nodeLoop;i++){ node2 = node2.next; } ListNode node3 = head; while(node2!=node3){ node2 = node2.next; node3 = node3.next; } return node2; } public ListNode meet(ListNode head){ ListNode slow = head; ListNode fast = head; if(head==null||head.next==null){ return null; } while(slow.next!=null&&fast.next!=null&&fast.next.next!=null){ slow = slow.next; fast = fast.next.next; if(slow==fast){ return slow; } } return null; }