说我有一个函数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);
}
}
答案 0 :(得分:7)
如果该函数是一个“黑盒子”,并且你能够找到任何个体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?"等同的问题有很多答案。
答案 1 :(得分:0)
对于你给出的fn,因为它除以4,长度为4,因为没有加值,0实际上是循环的开始而不是1.如果你使用它实现它,你实际上可以观察到它已经指出的图表。 由于这些是fn值,你可以使用链接列表,并且在fn返回的每个值上,如果它不存在则将它添加到列表中,否则你可以有一个循环。假设只有一个循环..