此题难度在于不适用额外空间
我们将这个问题的求解分解为一下几步:
1、进入环区段
使用快慢双指针,当二者第二次重合时,意味着我们进入了环中
2、计算环的长度
从重合位置开始,慢指针继续前进,每前进一步长度+1,直到回到重合位置
此时长度计数器即为环的长度L
3、接下来需要找环的入口
3.0、我打错了代码但是居然通过的方法
由于经过1、和2、后,我们的fast仍然位于第一次重合的位置
因此我们现在设置一个起始指针start指向头结点,然后两个指针一起走,
当重合时,返回这个节点
3.1、蠢一点但是好想的办法
从链表的头指针开始,我们对每个节点,都设置一个游标指针
令游标指针从每个节点出发,走L步,若走完后回到这个节点
则返回这个节点
3.2、快的办法
由于经过1、和2、后,我们的fast仍然位于第一次重合的位置
因此我们现在设置一个起始指针start指向头结点,并先走L步,
然后二者一起走,重合则返回节点
下面依次给出三种方法的实现
3.0 “桃花源方法”:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
if head == None:
return None
#双指针先进入环
slow = head
fast = head
start = 0
while True:
if start == 0:
start = 1
elif start == 1 and slow == fast:
cur = slow
break
if slow.next is None or fast.next is None or fast.next.next is None:
return None
slow = slow.next
fast = fast.next.next
this = cur
cur = cur.next
length = 1
while cur != this:
cur = cur.next
length += 1
start = head
while start != fast:
print(start.val)
print(fast.val)
start = start.next
fast = fast.next
return start
3.1 蠢一点但是好想的办法:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
if head == None:
return None
#双指针先进入环
slow = head
fast = head
start = 0
while True:
if start == 0:
start = 1
elif start == 1 and slow == fast:
cur = slow
break
if slow.next is None or fast.next is None or fast.next.next is None:
return None
slow = slow.next
fast = fast.next.next
this = cur
cur = cur.next
length = 1
while cur != this:
cur = cur.next
length += 1
start = head
index = 0
while True:
res = start
for i in range(length):
res = res.next
if res == start:
return res
else:
start = start.next
3.2 快的办法:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
if head == None:
return None
#双指针先进入环
slow = head
fast = head
start = 0
while True:
if start == 0:
start = 1
elif start == 1 and slow == fast:
cur = slow
break
if slow.next is None or fast.next is None or fast.next.next is None:
return None
slow = slow.next
fast = fast.next.next
this = cur
cur = cur.next
length = 1
while cur != this:
cur = cur.next
length += 1
start = head
end = start
for i in range(length):
end = end.next
while start != end:
#print(start.val)
#print(fast.val)
start = start.next
end = end.next
#fast = fast.next
return start