弗洛伊德的循环寻找算法

发布于 2024-09-26 15:07:52 字数 562 浏览 8 评论 0原文

我试图在 .NET 中的 C++ 上找到这个算法,但找不到,我找到了这个:

// Best solution
function boolean hasLoop(Node startNode){
  Node slowNode = Node fastNode1 = Node fastNode2 = startNode;
  while (slowNode && fastNode1 = fastNode2.next() && fastNode2 = fastNode1.next()){
    if (slowNode == fastNode1 || slowNode == fastNode2) return true;
    slowNode = slowNode.next();
  }
  return false;
}

但似乎不对,还是我错了?我怎样才能真正证明我的兔子最终会遇到乌龟呢?预先感谢您解释它到底是如何工作的,并proof

编辑

关于这个解决方案,我发现在常规算法中他们只使用一个快速迭代器,但在这里他们使用两个,为什么?

I'm trying to find this algorithm on C++ in .NET but can't, I found this one:

// Best solution
function boolean hasLoop(Node startNode){
  Node slowNode = Node fastNode1 = Node fastNode2 = startNode;
  while (slowNode && fastNode1 = fastNode2.next() && fastNode2 = fastNode1.next()){
    if (slowNode == fastNode1 || slowNode == fastNode2) return true;
    slowNode = slowNode.next();
  }
  return false;
}

but doesn't seem to be right, or am I wrong? How can I actually prove that my hare will meet tortoise at the end? Thanks in advance for any explanation how exactly does it work and proof

EDITED

About this solution, I found that in regular algorithm they use only one fast iterator but here they use two, why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

稀香 2024-10-03 15:07:52

您找到的代码中的想法似乎不错。使用两个快速迭代器是为了方便(尽管我确信这种“方便”,比如在 while 循环的条件下放置大量“动作”,应该避免)。您可以使用一个变量以更易读的方式重写它:

while (fastNode && fastNode.next()) {
    if (fastNode.next() == slowNode || fastNode.next().next() == slowNode) {
        return true;
    }
    fastNode = fastNode.next().next();
    slowNode = slowNode.next();
}

The idea in the code you've found seems fine. Two fast iterators are used for convenience (although I'm positive such kind of 'convenience', like putting a lot of 'action' in the condition of while loop, should be avoided). You can rewrite it in more readable way with one variable:

while (fastNode && fastNode.next()) {
    if (fastNode.next() == slowNode || fastNode.next().next() == slowNode) {
        return true;
    }
    fastNode = fastNode.next().next();
    slowNode = slowNode.next();
}
我是有多爱你 2024-10-03 15:07:52

算法是正确的。证明:

没有循环的情况是微不足道的:兔子会找到列表的末尾。

于是,就有了一个循环,兔子就进入了这个循环,疯狂地跑来跑去。最终,乌龟到达了循环的第一个节点。从这一点开始,两者都必须留在循环中:它们从一个节点出发的唯一途径是到达下一个节点,最终回到循环的第一个节点。 (画一张列表/图表来说服自己。)

由于兔子移动得更快,它最终会追上乌龟。根据循环的长度和进入循环之前遍历的节点数(重要的是奇数还是偶数,因此有四种情况),这可能会在奇数或偶数步后发生。这就是为什么兔子应该检查其当前节点和下一个节点是否存在乌龟。 (示例代码使用两个指针来实现此目的,尽管这并不是真正必要的。)

有关更正式的证明,请查看此 维基百科页面

The algorithm is correct. Proof:

The case of no cycle is trivial: the hare will find the end of the list.

So, there's a cycle, and the hare enters it, running around like crazy. Eventually, the tortoise reaches the first node of the cycle. From this point on, both necessarily stay in the cycle: the only way they can go from a node is to the next node, which eventually leads back to the first node of the cycle. (Draw a picture of the list/graph to convince yourself.)

Since the hare moves faster, it will eventually catch up with the tortoise. Depending on the length of the cycle and the number of nodes traversed before entering it (whether they are odd or even is what matters, so there are four cases), this may happen after an odd or an even number of steps. That's why the hare should check both its current node and the next node for the tortoise's presence. (The example code uses two pointers to achieve this, though that's not really necessary.)

For a more formal proof, check out this Wikipedia page.

最舍不得你 2024-10-03 15:07:52

该算法将在链表中找到循环。
可以使用一个快速节点来代替:

 function boolean hasLoop(Node startNode){
  Node slowNode = Node fastNode = startNode;
  while (slowNode && fastNode = fastNode.next() && fastNode = fastNode.next()){
    if (slowNode == fastNode) return true;
    slowNode = slowNode.next();
  }
  return false;
}

This algorithm will find a cycle in a linked list.
one fast node can be used instead:

 function boolean hasLoop(Node startNode){
  Node slowNode = Node fastNode = startNode;
  while (slowNode && fastNode = fastNode.next() && fastNode = fastNode.next()){
    if (slowNode == fastNode) return true;
    slowNode = slowNode.next();
  }
  return false;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文