142. Linked List Cycle II

Posted king-lps

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于142. Linked List Cycle II的主要内容,如果未能解决你的问题,请参考以下文章

142. Linked List Cycle II

142. Linked List Cycle II

LeetCode141 Linked List Cycle. LeetCode142 Linked List Cycle II

142. Linked List Cycle II

142. Linked List Cycle II

142. Linked List Cycle II