【问题标题】:Different approach to detecting cycle/loop in a linked list在链表中检测循环/循环的不同方法
【发布时间】:2021-01-18 20:54:32
【问题描述】:

所以我知道弗洛伊德的循环检测算法,但在研究这个问题时,我想出了另一个解决它的想法。

如果我们可以在遍历链表时将每个节点的'nextpointer'存储在一个向量/列表中,以及是否任何元素的频率大于1的计数。 如果向量/列表中的任何值出现不止一次,则基本上意味着单个节点已被指向两次(或更多),因此它成为一个循环。

我无法在 Python 3 中编写相同的代码。如果你们能帮助我,我将不胜感激。 谢谢。

class Node:
    head = None

    def __init__(self, data=None, nextnode=None):
        self.data = data
        self.next = nextnode

def findMergeNode(head1, head2):
    a = set()
    b = set()
    while (head1 and head2):
        a.add(head1)
        head1 = head1.next        
        b.add(head2)
        head2 = head2.next
    if (a.intersection(b)):
        return a.intersection(b)

【问题讨论】:

  • 这可以工作,但是 (1) 它需要 O(n) 空间,并且 (2) 在向量中查找需要 O(n)我>时间。第二个可以用一组来解决,但第一个仍然是一个主要缺点。
  • 欢迎来到 SO!有趣的问题。但是,您能否添加(摘录)您尝试对其进行编码并指出您没有成功的地方。否则问题是“请为我编码”类型。
  • @Timus 是的。抱歉我没有先发帖。

标签: python-3.x list pointers linked-list cycle-detection


【解决方案1】:

您提出的算法可以工作,但是

  1. 它需要 O(n) 个空间,并且
  2. 在列表(向量)中查找需要 O(n) 时间

第二个可以通过使用集合来解决,但第一个仍然是一个主要缺点。

这是一个带有集合的基本实现:

class Node:
    def __init__(self, val, next=None):
        self.val = val
        self.next = next

    def add(self, val):
        self.next = Node(val)
        return self.next  # to allow chaining

    def hascycle(self):
        node = self
        visited = set()
        while node:
            if node in visited:  # been here before!
                return True
            visited.add(node)
            node = node.next
        return False

# Demo graph: a -> b -> c -> d -> e -> b
a = Node("a")
e = a.add("b").add("c").add("d").add("e")
# make a back reference from e to b:
e.next = a.next
print(a.hascycle())  # True

注意visited 的大小如何变得与链表本身的数量级相同。当然,当没有检测到循环时,对所有节点的引用都存储在集合中。

弗洛伊德算法的美妙之处在于它只使用常量空间(当然不包括列表本身)。所以与链表的大小无关,它总是会使用相同的空间来操作。

【讨论】:

  • 是的!非常感谢A2A。弗洛伊德的算法当然是一种美。我只是想看看我的方法是否也能奏效。 :)
  • 如果这个答案适合你的需要,那么别忘了mark it as accepted
猜你喜欢
  • 1970-01-01
  • 2012-06-18
  • 2011-11-15
  • 1970-01-01
  • 2011-12-04
  • 2016-09-11
  • 2012-01-06
相关资源
最近更新 更多