【问题标题】:Cycle Detection Algorithm循环检测算法
【发布时间】:2011-09-17 20:06:45
【问题描述】:

假设我有一个函数 f:

f(0) = 0
f(i) = (i - 1) % 4

f(0..12):

0 0 1 2 3 0 1 2 3 0 1 2 3

我想找到循环开始和循环长度,分别是 1 和 4。 龟兔算法适用于迭代函数,但我没有迭代函数。 是否有其他算法适用于非迭代函数,或者可以为此修改龟兔算法吗?

编辑:

使用 Jason S 的答案,我设法想出了这个,这似乎有效:

public static Tuple<int, int> ModifiedTortoiseHare(Func<int, int> f, int x0 = 0, int checks = 4)
{
    for (; ; x0++)
    {
        int lam = 0, tortoise, hare;

        do
        {
            lam++;
            tortoise = f(x0 + lam);
            hare = f(x0 + 2 * lam);
        } while (tortoise != hare);

        int mu = -1;

        do
        {
            mu++;
            tortoise = f(x0 + mu);
            hare = f(x0 + mu + lam);
        } while (tortoise != hare);

        if (mu != 0) continue;

        bool correct = true;
        int lamCheckMax = lam * checks;

        for (int x = 0; x < lamCheckMax; x++)
        {
            if (f(x0 + x + mu) != f(x0 + x + mu + lam))
            {
                correct = false;
                if (mu != 0) x0 += mu - 1;
                break;
            }
        }

        if (correct) return Tuple.Create(x0 + mu, lam);
    }
}

【问题讨论】:

  • @SuprDewd:您是在寻找以最长长度重复至少两次的循环,还是以最长总长度重复的循环? (例如,`01010101010123401234' 是 f(0) = 0、f(1) = 1、f(2) = 0、f(3) = 1 等的简写,它有 6 个循环 0 1,总长度为 12 , 和 0 1 2 3 4 的 2 个循环,总长度为 10) 或其他?
  • ...或者你知道 f(x) 总是遵循某种特定的形式吗? (例如 f(x) = (x-x0) % m 对于所有 x > 一些 x1)
  • 我正在寻找最长的周期。我上面的代码将返回起始 0 和长度 2,但我很确定这很难避免。
  • 例如序列:123123123123123123...*50 亿次 123*...123456123456123456123456...这样的序列很难解释。

标签: algorithm function detection cycle floyd-cycle-finding


【解决方案1】:

如果该函数是一个“黑匣子”,并且您有能力找到任何单个 x 的 f(x)(无论是对实数有效还是仅对整数有效),但您不知道其他任何东西,则有没有找到循环开始和长度的一般方法。例如,考虑函数

f(k) = (k - 1) % 4 + g(k)
g(k) = max(0, k-1000000)

然后 f(k) 看起来它每 4 个整数重复一次,但是当你到达 k = 1000000 时,模式就会停止。


如果函数具有有限范围,并且您可以测试所有整数,则可以使用龟/兔算法 (= Floyd's cycle-finding algorithm) 提供帮助。

不是迭代函数评估,而是计算 f(k0 + k) 和 f(k0 + 2*k) 直到它们匹配,此时可疑周期为 k,您只需重复所有值以验证循环继续。

您的问题似乎与"How should I find repeated word sequences?" 相同,有多个答案。

【讨论】:

  • 但是“您只需要重复所有值以验证循环是否继续”是什么意思?可能还有无限多的值,我无法将它们全部检查...
  • 我说“如果函数有一个有限范围”——你没有在你的问题陈述中说这个函数是在有限范围还是无限范围内。如果有限,请全部检查。如果无限,则需要另一个成功/失败标准,因为您无法全部检查。
【解决方案2】:

对于您给出的 fn,因为它除以 4 长度为 4,并且由于没有添加任何值,因此 0 实际上是循环的开始,而不是 1。如果您使用它来实现它,您实际上可以观察到这一点已经指出的图表。 由于这些是 fn 值,您可以改用链表,并且在 fn 返回的每个值上,如果它还没有,则将其添加到列表中,否则您可以有一个循环。假设只有 1 个循环..

【讨论】:

    猜你喜欢
    • 2012-06-18
    • 2011-11-15
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 2016-09-11
    • 2015-07-20
    • 2016-05-12
    相关资源
    最近更新 更多