【问题标题】:Can my tortoise vs. hare race be improved?我的龟兔赛跑可以改进吗?
【发布时间】:2011-03-17 15:56:48
【问题描述】:

这是我在链表中​​检测循环的代码:

do
{
    hare = hare.next();
    if (hare == back) return;

    hare = hare.next();
    if (hare == back) return;

    tortoise = tortoise.next();
}
while (tortoise != hare);
throw new AssertionError("cyclic linkage");
  1. 有没有办法摆脱循环内的代码重复?

  2. 在让乌龟向前迈出一步后,我是否认为我不需要检查是正确的?在我看来,乌龟永远不会在兔子之前到达列表的末尾(与寓言相反)。

  3. 还有其他方法可以简化/美化这段代码吗?

【问题讨论】:

  • 如果您设计back 来引用具有指向其自身的“下一个”字段的节点,那么您可以将4 行替换为hare = hare.next().next(); if (hare==back) return;。不过,不知道我是否可以更改列表。
  • @Steve:back可以直接引用自己(已经是哨兵了)。

标签: algorithm linked-list code-duplication control-flow


【解决方案1】:

有没有办法摆脱代码 循环内重复?

怎么样:

for(int i = 0; i < 2; i++)
{
    hare = hare.next();
    if (hare == back) return;
}

 tortoise = tortoise.next();

无论如何,这并不是一个巨大的改进。

让乌龟向前迈出一步后,我是否认为我不需要检查?

是的,正如您正确推理的那样,乌龟总是在兔子移动之前之后;所以乌龟总是覆盖以前覆盖过的地面。

如果数据结构在比赛期间因任何原因发生了变异,这当然不再正确(但如果是这样,您将遇到更大的问题)。

任何其他简化/美化的方法 这段代码?

我想不到。

【讨论】:

    【解决方案2】:

    这是我根据 Steve 的评论改进的代码(将后哨节点链接到自身):

    while (hare != back)
    {
        tortoise = tortoise.next();
        hare = hare.next().next();
        if (hare == tortoise) throw new AssertionError("cyclic linkage");
    }
    

    我没有看到任何会破坏客户端代码的地方,我的单元测试证实了这一点。太好了:)

    【讨论】:

    • 这不会对长度为 1 的列表给出误报吗?不幸的是,您需要先检查 hareback,然后再检查 tortoise
    【解决方案3】:

    您可以使用单个 if 语句并使用 || 是短路运算符这一事实。这个稍微简洁一点,但是可能比较难理解,还有代码重复。

        do
        {
            if ((hare = hare.next()) == back || 
                (hare = hare.next()) == back) 
                    return;            
            tortoise = tortoise.next();
        }
        while (tortoise != hare);
    

    【讨论】:

      【解决方案4】:

      为避免重复,您可以使用for (int i = 0; i &lt; 2; i++) 循环。除此之外,我认为您几乎已经获得了最简单的代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-17
        • 1970-01-01
        • 2016-05-12
        • 2021-04-20
        • 2021-02-10
        • 1970-01-01
        • 2015-01-30
        相关资源
        最近更新 更多