有一个任务给定一个自然数 n,从 0 到 1 确定不包含两个连续序列的长度为 n 的序列的数量。
有一个答案
def seq_count(n, p = 0):
if not n: return 1
return seq_count(n - 1, 0) + (0 if p else seq_count(n - 1, 1))
您需要迭代地重写。
seq_count(3)将返回5,因为可能的组合:
000 001 011 111 010 100 110 101
连续不包含 2 个单位:
000 001 010 100 101
但是为什么它起作用是完全不可理解的,这就是为什么我要求你重写它的循环。
在这种情况下,递归解决方案(通常是动态规划问题的情况)从字面上描述了解决方案:也就是说
f(0...) = f(00..) + f(01..),f(1...) = f(10..)长度为 n 的不包含 11 的位序列的数量等于长度为 (n- 1)从0开始,如果前一位不为1,加上以1开头的序列数(排除11):这几乎与正面解决方案一样清晰(要对所有长度为 n 位的位序列进行排序,计算有多少不包含 11):
循环可以隐藏解决方案的明显性:
所有选项产生相同的结果:
结果:
通过添加
@functools.lru_cache(maxsize=5)beforecount(),您可以记住之前的几个结果,以免重新计算它们。如果不需要确切的结果(一个近似值就足够了),那么有一些封闭的公式可以让您在 O (1) 时间内找到结果。有关详细信息,请参阅斐波那契数列的偶数和的答案中的链接。
您可以重复生成组合并计算那些连续没有两个单元的组合:
有一个算法,现在你可以检查一下:
火柴:
PS。我知道算法
seq_count_v2没有优化,但我决定展示这个想法本身让我们试着不给鱼,而是给鱼竿。
假设有一个长度为K的规则序列。这个序列可以以0结尾-那么至少0,至少可以添加1。如果它以1结尾,那么只能添加0。或者另一种解释:一个0序列,可以从较短的0序列和较短的1序列中得到,但1序列只能从0序列中得到。
表示第一个 F0(K),第二个 F1(K) 的数量。它们的数量取决于先前长度的序列数量:
剩下的就是设置单位长度的初始值,并循环更新值。
PS 结果序列包含一些非常显着的数字