周期检测算法

| 假设我有一个函数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);
    }
}
    
已邀请:
        如果函数是\“ black box \”(黑盒),并且您能够找到任意单个x的f(x)(对于实数有效还是仅对整数有效),但是您不知道其他任何内容,没有找到循环起点和长度的一般方法。例如考虑功能
f(k) = (k - 1) % 4 + g(k)
g(k) = max(0, k-1000000)
那么f(k)看起来每4个整数重复一次,但是当您达到k = 1000000时,模式停止。 如果函数的范围是有限的,并且您可以测试所有整数,则可以使用草龟/野兔算法(= Floyd's的循环查找算法)来提供帮助。 无需迭代函数求值,而是计算f(k0 + k)和f(k0 + 2 * k)直到匹配为止,此时可疑周期为k,您只需要重复所有值以验证循环是否继续。 您的问题似乎与\“我应该如何查找重复的单词序列?\”等效,其中包含许多答案。     
        对于您给定的fn,因为将其除以4的长度为4,并且由于未添加任何值,所以0实际上是循环的开始,而不是1。如果您确实使用图实现了fn,则可以观察到这一点已经指出。 由于这些是fn值,因此您可以使用链接列表,并且fn返回的每个值都将其添加到列表中(如果尚未存在),否则您可以有一个循环。假设只有1个循环。     

要回复问题请先登录注册