<p>您可以使用<a href="https://docs.python.org/3/library/itertools.html#itertools.product" rel="nofollow noreferrer">^{<cd1>}</a>生成数字,然后转换为字符串表示形式:</p>
<pre><code>import itertools as it
def new(n):
s = []
for digits in it.product((0, 1, 2), repeat=n):
if sum(digits) == n:
s.append(''.join(str(x) for x in digits))
return s
</code></pre>
<p>这给了我大约7倍的加速:</p>
<pre><code>In [8]: %timeit enumerateSpin(12)
2.39 s ± 7.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [9]: %timeit new(12)
347 ms ± 4.26 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
</code></pre>
<p>在Python 3.9.0(IPython 7.20.0)(Linux)上测试</p>
<p>上面的过程使用<code>it.product</code>也生成了我们通过推理知道它们不符合条件的数字(这是所有数字的一半的情况,因为数字的总和必须等于数字的数目)。对于<code>n</code>位,我们可以计算最终总计为<code>n</code>的<code>2</code>、<code>1</code>和<code>0</code>位的各种计数。然后我们可以生成这些数字的所有<a href="https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.distinct_permutations" rel="nofollow noreferrer">distinct permutations</a>,从而只生成相关数字:</p>
<pre><code>import itertools as it
from more_itertools import distinct_permutations
def new2(n):
all_digits = (('2',)*i + ('1',)*(n-2*i) + ('0',)*i for i in range(n//2+1))
all_digits = it.chain.from_iterable(distinct_permutations(d) for d in all_digits)
return (''.join(digits) for digits in all_digits)
</code></pre>
<p>特别是对于大量的<code>n</code>,这提供了额外的、显著的加速:</p>
<pre><code>In [44]: %timeit -r 1 -n 1 new(16)
31.4 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
In [45]: %timeit -r 1 -n 1 list(new2(16))
7.82 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
</code></pre>
<p>请注意,上述解决方案<code>new</code>和<code>new2</code>具有O(1)内存缩放(将<code>new</code>更改为<code>yield</code>而不是<code>append</code>)</p>