题目
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Note: Do not modify the linked list.
Follow up:
Can you solve it without using extra space?
题目要求
给定一个链表,如果链表中有环路,返回环路的起点,否则返回null。
解题思路
此题是参考了南郭子綦的思路。并引用了南郭子綦的图。
如果仅仅是判断链表是否有环路,可以通过快慢指针来做这件事情。让快指针每次走两步,慢指针每次走一步。如果两个指针可以相遇,说明有环路。如果要找到环路的起点。则需要进一步的处理
上图是一个带有环路的链表。从链表头到环路起点步数为K,从起点到相遇点步数为M,环路长度为L。
那么我们有,快慢指针相遇时所走过的步数:
step_slow = K + M
step_faster = K + M + n*L
又因为快指针每次都多走一步:
step_faster = 2 * step_slow
由以上三个公式可以推断出
K = (n-1)L + L - M
所以,当快慢指针在相遇点相遇后,让慢指针回到head,faster留在相遇点。然后同时向前走,两个指针都是每次走一步,这样当慢指针走到起点时,快指针也会走到起点。
代码
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None or head.next == None:
return None
faster = slow = head
while faster and faster.next:
faster = faster.next.next
slow = slow.next
if faster == slow:
break
if slow == faster:
slow = head
while slow != faster:
slow = slow.next
faster = faster.next
return slow
return None