Linked List Cycle | & ||

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

Example

Given -21->10->4->5, tail connects to node index 1, return true.

分析:

方法一:使用HashSet保存每一个节点。

 1 /**
 2  * Definition for ListNode.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int val) {
 7  *         this.val = val;
 8  *         this.next = null;
 9  *     }
10  * }
11  */ 
12 public class Solution {
13     /**
14      * @param head: The first node of linked list.
15      * @return: True if it has a cycle, or false
16      */
17     public boolean hasCycle(ListNode head) {  
18         if (head == null) return false;
19         HashSet<ListNode> set = new HashSet<ListNode>();
20         while (head != null) {
21             if (set.contains(head)) {
22                 return true;
23             }
24             set.add(head);
25             head = head.next;
26         }
27         return false;
28     }
29 }

方法二:

设置两个指针指向单链表的head, 然后开始遍历,第一个指针走一步,第二个指针走两步,如果没有环,它们会直接走到底,如果有环,这两个指针一定会相遇。

 1 public class Solution {
 2     public boolean hasCycle(ListNode head) {  
 3         if (head == null) return false;
 4         ListNode slow = head;
 5         ListNode quick = head.next;
 6         while (slow != null && quick != null) {
 7             if (slow == quick) return true;
 8             slow = slow.next;
 9             quick = quick.next;
10             if (quick != null) {
11                 quick = quick.next;
12             }
13         }
14         return false;
15     }
16 }

Linked List Cycle II

Given a linked list, return the node where the cycle begins.

If there is no cycle, return null.

Example

Given -21->10->4->5, tail connects to node index 1,return 10。

方法一:

使用HashSet

 1 /**
 2  * Definition for ListNode.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int val) {
 7  *         this.val = val;
 8  *         this.next = null;
 9  *     }
10  * }
11  */ 
12 public class Solution {
13     /**
14      * @param head: The first node of linked list.
15      * @return: The node where the cycle begins. 
16      *           if there is no cycle, return null
17      */
18     public ListNode detectCycle(ListNode head) {  
19         if (head == null || head.next == null) return null;
20         
21         Set<ListNode> set = new HashSet<ListNode>();
22         
23         while (head!= null) {
24             if (set.contains(head)) {
25                 return head;
26             } else {
27                 set.add(head);
28             }
29             head = head.next;
30          }
31          return null;
32     }
33 }

方法二:

 1 public static ListNode detectCycle(ListNode head) {
 2     ListNode slow = head;
 3     ListNode fast = head;
 4 
 5     while (true) {
 6         if (fast == null || fast.next == null) {
 7             return null;    //遇到null了,说明不存在环
 8         }
 9         slow = slow.next;
10         fast = fast.next.next;
11         if (fast == slow) {
12             break;    //第一次相遇在Z点
13         }
14     }
15 
16     slow = head;    //slow从头开始走,
17     while (slow != fast) {    //二者相遇在Y点,则退出
18         slow = slow.next;
19         fast = fast.next;
20     }
21     return slow;
22 }

分析:上面的代码为何能够找到环的起始位置?


假设环的长度是 m, 进入环前经历的node的个数是 k , 那么,假设经过了时间 t,那么速度为2 的指针距离起始点的位置是:  k + (2t - k) % m = k + (2t - k) - xm . 同理,速度为1的指针距离起始点的位置是 k + (t - k) % m = k + (t - k) - ym。

如果 k + (2t - k) - xm =  k  + (t - k) - ym ,可以得到 t = m (x - y)。 那么当 t 最小为m的时候,也就是说,两个指针相聚在距离环起始点 m - k 的环内。换句话说,如果把一个指针移到链表的头部,然后两个指针都以 1 的速度前进,那么它们经过 k 时间后,就可以在环的起始点相遇。

Reference: http://www.cnblogs.com/hiddenfox/p/3408931.html

转载请注明出处:cnblogs.com/beiyeqingteng/

posted @ 2016-07-03 11:45  北叶青藤  阅读(188)  评论(0编辑  收藏  举报