142. Linked List Cycle II

1. 原始题目

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Note: Do not modify the linked list.

 

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.

 

2. 题目理解

这道题是 141. Linked List Cycle的升级版。就是不仅要确认是否有环。若有环的话,还要输出环的入口结点。

所以第一步是141题的做法,先确认有无环。然后要确认环中元素的个数m。然后快慢指针从头开始走,快指针先走m步,然后快慢指针同步一步一步地走,当再次相遇时,两者就在环的入口处啦。

 

3. 解题

 1 class Solution(object):
 2     def detectCycle(self, head):
 3         """
 4         :type head: ListNode
 5         :rtype: ListNode
 6         """
 7         
 8         if not head or not head.next:
 9             return None
10         cur = head
11         pre = head
12         exist_cycle = False   # default no cycle
13         while pre:
14             pre = pre.next
15             cur = cur.next
16             if pre:
17                 pre = pre.next
18             if pre==cur:
19                 exist_cycle = True
20                 break                     # 以上步骤确认是否有环
21             
22         if exist_cycle:
23             num = 1
24             while(pre.next!=cur):
25                 pre = pre.next
26                 num+=1                    # num返回环中元素的个数  
27                 
28             pre = head
29             cur = head
30            
31             for _ in range(num):          # 快指针先走num步
32                 pre = pre.next
33             while(pre!=cur):           
34                 pre = pre.next
35                 cur = cur.next
36             return pre                    # 两者相遇即相等时就是环的入口啦 
37         

这是常规解法。Leetcode上一个小哥根据公式计算出一种更间接的操作:尤其是最后的一个循环

 1 class Solution:
 2     # @param head, a ListNode
 3     # @return a list node
 4     def detectCycle(self, head):
 5         try:
 6             fast = head.next
 7             slow = head
 8             while fast is not slow:
 9                 fast = fast.next.next
10                 slow = slow.next
11         except:
12             # if there is an exception, we reach the end and there is no cycle
13             return None
14 
15         # since fast starts at head.next, we need to move slow one step forward
16         slow = slow.next
17         while head is not slow:
18             head = head.next
19             slow = slow.next
20 
21         return head

 

4. 验证

 1 # 新建链表1
 2 listnode1 = ListNode_handle(None)
 3 s1 = [3,2,666,0,-4]
 4 for i in s1:
 5     listnode1.add(i)
 6 listnode1.cur_node.next = listnode1.head.next.next       # 构建循环链表,即将尾指针再指向头后面后面的元素,即6666
 7 
 8 
 9 s = Solution()
10 head = s.detectCycle(listnode1.head)                     # python3.5
11 print(head)
12 print(head.val)

<__main__.ListNode object at 0x00000247132B9940>
666

posted @ 2019-04-06 11:53  三年一梦  阅读(108)  评论(0编辑  收藏  举报