我需要系统地迭代(偶数)长度为n的平衡二进制字符串集合,即由相同数量的1和0组成的二进制字符串。 (这个问题可以用许多等价方式来陈述;例如,给定集合S = {1,2,...,n},如何迭代S的平衡二分区或大小为n / 2的S的子集。 )最有效的方法是什么?
最天真的算法是简单地迭代所有二进制字符串(例如,以标准字典顺序),然后跳过所有不平衡字符串。但这是非常低效的:有2 ^ n个长度为n的二进制字符串,但只有(n选择n / 2)是平衡的。通过斯特林的近似,这个数量渐近地增长为$ \ sqrt {2 /(\ pi n)} 2 ^ n $,所以只有一小部分~1 / n的二进制字符串是平衡的。
在我看来,一个更有效的实现可能会是这样的:你从字符串000 ... 0111 ... 1开始,然后通过一系列相邻的转置01跳过1的左边 - > ; 10.但我无法找到一种方法来组织转置,以便每个平衡的二进制字符串生成一次。例如,如果你总是转置最左边的01,那么你会错过许多字符串(例如0110),但是如果你在每一步都将每个可能的转置分支到一个树中,那么你将超过许多字符串(例如0101 - &gt ;可以通过以任何顺序执行两个转换来达到1010。
(如果算法很容易推广到能够迭代一组具有任意固定不平衡的n位二进制字符串,那将是很好的,但不是必需的。)
答案 0 :(得分:1)
这是一个Python递归(很容易转换为堆栈迭代;内部g
函数中可用的任意固定不平衡):
def f(n):
def g(n, k, s):
if len(s) == n:
return [s]
if len(s) + k == n:
return [s + (n - len(s)) * '1']
if k == 0:
return [s + (n - len(s)) * '0']
return g(n, k, s + '0') + g(n, k - 1, s + '1')
return g(n, n / 2, '')
输出:
=> f(6)
=> ['000111', '001011', '001101', '001110', '010011', '010101', '010110', '011001', '011010', '011100', '100011', '100101', '100110', '101001', '101010', '101100', '110001', '110010', '110100', '111000']