Floyd 判圈算法
摘自维基百科, LeetCode 上 141题 Linked List Cycle 用到这个, 觉得很有意思. 记录一下.
链接: https://zh.wikipedia.org/wiki/Floyd%E5%88%A4%E5%9C%88%E7%AE%97%E6%B3%95
用于判断链表上是否有环, 并给出环的起点和长度.
也叫做龟兔赛跑算法, 拥有线性时间复杂度和常数空间复杂度.
原理:
1. 判定是否有环: 假设 t 和 h 同时从起点 S 出发, t 的步长是一步, h 的步长是两步, 如果有环, 则 t 与 h 一定会在环上一点相遇, 记为 M.
2. 环的长度: 如果判定有环, h 不动, t 绕环一圈回到 h, 就是环的长度.
3. 环的起点: h 仍不动, t 回到起点 S, 这时候 t 按原路径走到 h 的距离, 是环的整数倍. 这时候 t 和 h 同时以相同步长(只能是一步)前进, 相遇处便是环的起点, 记为 P.
代码:
# Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = x # self.next = None class Solution(object): def hasCycle(self, head): """ :type head: ListNode :rtype: tuple (bool, length, start_node) """ try: slow = head.next fast = head.next.next while slow is not fast: slow = slow.next fast = fast.next.next slow = slow.next length = 1 while slow is not fast: slow = slow.next length += 1 slow = head while slow is not fast: slow = slow.next fast = fast.next return True, length, slow except: return False, None, None