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