【问题标题】:Algorithm to determine whether loop exists in a linked list判断链表中是否存在循环的算法
【发布时间】:2016-10-06 00:50:02
【问题描述】:

所以最近遇到了判断链表中是否存在循环的算法。代码如下:

public boolean hasCycle(ListNode head) {
    if (head == null) {
        return false;
    }
    ListNode fast = head;
    ListNode slow = head;
    while (fast != null) {
        if (fast.next == null) {
            return false;
        }
        if (fast.next == slow) {
            return true;
        }
        fast = fast.next.next;
        slow = slow.next;
    }
    return false;
}

在试图证明这个算法的正确性时,我想到了一个想法: 假设循环的周长是“a”,两个指针相遇之前经过的时间是“t”。由于“快”节点的移动速度是“慢”节点的两倍,我们可以得到数学关系:

2t mod a = t mod a

现在“a”是一个常数,代表周长,“t”可以是1,2,3....那么,我如何证明无论“a”是什么值,我们总能找到一个“ t" 这样上面的方程是可解的?

【问题讨论】:

  • 如果循环不是从第一个节点开始,等式是否正确?例如:1->2, 2->3, 3->4, 4->5, 5->3, 循环 = {3,4,5,3}
  • 任何t = 0 mod a 解决2t = t mod a。您还需要t >= s,其中需要s 步骤才能进入循环。
  • @MattTimmermans 嗯...我想了一会儿之后可能是一样的:2t -s = t-s (a) 所以 2t = t (a),但不确定
  • @shole,你需要这两个条件。如果进入一个长度为 10 的循环需要 13 步,那么指针将在 t=20 和 t=30 处相遇,而不是 t=10

标签: algorithm loops linked-list


【解决方案1】:

你在正确的轨道上!提示:a 次迭代后你的公式会发生什么变化?

【讨论】:

    【解决方案2】:

    假设两个指针在循环中的同一点开始(这不算是相遇)

    2t = t (a)

    => 2t - t = 0 (a)

    => t = 0 (a)

    这意味着在 t = a*k 时,两个指针将在经过的时间是循环长度的倍数后在起点相遇。

    对于所有a >= 2 都是如此,因为当时间等于所有k>1k*a 时,慢速指针恰好运行k 个周期,而快速指针运行速度快两倍,因此它运行2k 个周期,他们仍然在同一点相遇,这是起点。

    【讨论】:

    • 我在你的第二步迷路了:(你如何从 2t = t (a) 得到 2t - t = 0 (a)?
    • 两边都减去t%a?
    猜你喜欢
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2011-03-01
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    相关资源
    最近更新 更多