Floyd 判圈算法

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

 

posted @ 2017-03-04 17:36  Herbert_Kwok  阅读(247)  评论(0编辑  收藏  举报