一 单链表中的双指针
快慢指针找环的问题
如果存在环,快指针总能追上慢指针。
什么速度合适?其他速度怎么样?
例子:
Linked List Cycle
Given a linked list, determine if it has a cycle in it.
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if head is None or head.next is None:
return False
slow = head
fast = head.next
# 比较安全的速度是fast是slow的两倍,也就是说每次fast比slow多跑一格。
# 如果fast过快,而且环很小的话,fast每次恰好跨过一个环,和slow永远无法相遇
# 如果fast过快,需要判断的条件过长 fast.next fast.next.next fast.next.next...
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
比较简单的做法,用hash表记录访问过的位置。空间是O(n)的。快慢指针的方法空间是O(1)。
快慢指针相遇的点是不确定的,但是快指针比慢指针多走过的距离是确定,恰好等于慢指针到环入口的位置。
用三个阶段,很容易解释:
设起点到环入口点的距离为x, 环的的长度为c,
一, 当slow指针到达入口点的时候,t = x次, fast移动的距离为 2 * x,相当于fast不仅到达了环而且已经在环中走了x的距离,此时fast距离slow的距离为 c - x
二 在环中的追击问题,fast 距离 slow 为 c - x,又因为fast的相对速度为1, 所以 移动 t = c - x次后, slow和fast相遇。当slow和fast相遇,此时slow 走过了 t * 1 = c - x 的距离, 那么相遇点距离 入口的距离就是 c - (c - x) = x
三 得到了距离关系,从起点到入口点距离为x, 从相遇点到入口点的距离也是x,所以两个点同时同速移动就一定会在入口点
相遇。
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
cur = head
visited = set()
while cur:
if cur in visited:
return cur
else:
visited.add(cur)
cur = cur.next
return None
# if head is None or head.next is None:
# return None
# slow = head
# fast = head
# hascycle = False
# while fast.next and fast.next.next:
# fast = fast.next.next
#