【发布时间】:2016-05-23 05:18:48
【问题描述】:
简短说明。
我有一个数字序列[0, 1, 4, 0, 0, 1, 1, 2, 3, 7, 0, 0, 1, 1, 2, 3, 7, 0, 0, 1, 1, 2, 3, 7, 0, 0, 1, 1, 2, 3, 7]。如您所见,从第三个值开始,序列是周期性的,周期为 [0, 0, 1, 1, 2, 3, 7]。
我正在尝试从这个序列中自动提取这段时间。问题是我既不知道周期的长度,也不知道序列从哪个位置变为周期。
完整解释(可能需要一些数学知识)
我正在学习组合博弈论,该理论的基石需要计算博弈图的Grundy values。这会产生无限序列,在许多情况下会变成eventually periodic。
我找到了一种有效计算粗略值的方法(它返回给我一个序列)。我想自动提取这个序列的偏移量和周期。我知道看到序列的一部分[1, 2, 3, 1, 2, 3] 你不能确定[1, 2, 3] 是一个句号(谁知道下一个数字可能是4,这打破了假设),但我不感兴趣在如此复杂的情况下(我假设序列足以找到真实的周期)。另外问题是序列可以在句号中间停止:[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, ...](句号仍然是1, 2, 3)。
我还需要找到最小的偏移量和周期。例如原始序列,偏移量可以是[0, 1, 4, 0, 0]和句点[1, 1, 2, 3, 7, 0, 0],但最小的是[0, 1, 4]和[0, 0, 1, 1, 2, 3, 7]。
我低效的方法是尝试每一个可能的偏移量和每一个可能的周期。使用该数据构建序列,并检查它是否与原始数据相同。我没有做任何正态分析,但它看起来至少在时间复杂度方面是二次的。
这是我的快速 Python 代码(尚未正确测试):
def getPeriod(arr):
min_offset, min_period, n = len(arr), len(arr), len(arr)
best_offset, best_period = [], []
for offset in xrange(n):
start = arr[:offset]
for period_len in xrange(1, (n - offset) / 2):
period = arr[offset: offset+period_len]
attempt = (start + period * (n / period_len + 1))[:n]
if attempt == arr:
if period_len < min_period:
best_offset, best_period = start[::], period[::]
min_offset, min_period = len(start), period_len
elif period_len == min_period and len(start) < min_offset:
best_offset, best_period = start[::], period[::]
min_offset, min_period = len(start), period_len
return best_offset, best_period
它返回了我想要的原始序列:
offset [0, 1, 4]
period [0, 0, 1, 1, 2, 3, 7]
还有什么更高效的吗?
【问题讨论】:
-
除非有一个已知的周期长度上限,否则您不能这样做。一个看似周期性的序列可能会在十亿个元素之后偏离模式。
-
@Henry,谢谢,但我知道并在我的问题中解释了它:
I am aware that seeing a part of the sequence [1, 2, 3, 1, 2, 3] you can't be sure that [1, 2, 3] is a period (who knows may be the next number is 4, which breaks the assumption), but I am not interested in such intricacies (I assume that the sequence is enough to find the real period) -
@SalvadorDali dfa 代表“确定性有限自动机”。无论如何,这里已经问过这个问题:stackoverflow.com/questions/18620942/…
-
你考虑过自相关吗?
-
@MBo 不,我什至不知道这个词。乍一看,它看起来很有希望。会看看。