通过在 Python 中链接可迭代对象来表示循环
representing recurrence by chaining iterables in Python
我正在解决一个在二叉树中有层次的问题。我得到一个级别,然后是一个职位。
第二关是[True, False]
。
第三层是[True, False, False, True]
。
第四个[True, False, False, True, False, True, True, False]
,依此类推。
为了解决这个问题,我可能需要多次计算这个序列以获得该级别给定位置的元素。
对于初始数组pattern = [True, False]
我想做类似的事情:
for _ in range(level):
pattern = pattern + [not elem for elem in pattern]
显然,对于较大的限制,这对我来说效果不佳。到目前为止,我尝试使用 itertools
中的 chain
方法来解决问题,但没有结果。在 Python 中表达这一点的内存有效方式是什么?
编辑
这满足了我的要求,但仍然不符合我正在寻找的运行时要求。
for _ in range(level):
lsb, msb = tee(pattern)
pattern = chain(lsb, map(lambda x: not x, msb))
最终,解决方案涉及找到相关目标元素的全局索引,并确定有多少 'right' 从根(基本情况 = 1)到它的路径,观察如果采用左路径,从父级到子级的状态不会改变,但如果采用右路,则状态会翻转。看来大多数聪明的解决方案都是基于这个事实。
What is a memory efficient way to express this in Python?
由于您使用的方法使每次迭代所需的内存翻倍,因此它不容易扩展。找个解析的方法可能会更好
下面的生成器需要 O(1) 的时间来生成每个元素。而且,至关重要的是,计算下一个值 仅取决于索引和前一个值 。
def gen():
yield True
n, prev = 1, 1
while True:
x = n ^ n - 1
y = x ^ x >> 1
if y.bit_length() % 2:
z = 1 - prev
else:
z = prev
yield bool(z)
prev = z
n += 1
像这样的递归关系允许计算常量内存中的元素。用 cython 或 pypy 实现这个想法应该会显着提高性能。
尝试一个一个地生成元素是个坏主意,将它们全部保存起来更糟糕。只需要一个元素的值,直接计算即可。
假设您想要的元素位于索引 2**i + k
,其中 k < 2**i
。那么这个元素就是索引k
处元素的否定,索引k
处的元素可以用同样的方式计算。您最终会为所需索引的二进制表示中的每个设置位否定一次元素 0。如果有偶数个设置位,则值为 True。否则,值为 False。
我正在解决一个在二叉树中有层次的问题。我得到一个级别,然后是一个职位。
第二关是[True, False]
。
第三层是[True, False, False, True]
。
第四个[True, False, False, True, False, True, True, False]
,依此类推。
为了解决这个问题,我可能需要多次计算这个序列以获得该级别给定位置的元素。
对于初始数组pattern = [True, False]
我想做类似的事情:
for _ in range(level):
pattern = pattern + [not elem for elem in pattern]
显然,对于较大的限制,这对我来说效果不佳。到目前为止,我尝试使用 itertools
中的 chain
方法来解决问题,但没有结果。在 Python 中表达这一点的内存有效方式是什么?
编辑
这满足了我的要求,但仍然不符合我正在寻找的运行时要求。
for _ in range(level):
lsb, msb = tee(pattern)
pattern = chain(lsb, map(lambda x: not x, msb))
最终,解决方案涉及找到相关目标元素的全局索引,并确定有多少 'right' 从根(基本情况 = 1)到它的路径,观察如果采用左路径,从父级到子级的状态不会改变,但如果采用右路,则状态会翻转。看来大多数聪明的解决方案都是基于这个事实。
What is a memory efficient way to express this in Python?
由于您使用的方法使每次迭代所需的内存翻倍,因此它不容易扩展。找个解析的方法可能会更好
下面的生成器需要 O(1) 的时间来生成每个元素。而且,至关重要的是,计算下一个值 仅取决于索引和前一个值 。
def gen():
yield True
n, prev = 1, 1
while True:
x = n ^ n - 1
y = x ^ x >> 1
if y.bit_length() % 2:
z = 1 - prev
else:
z = prev
yield bool(z)
prev = z
n += 1
像这样的递归关系允许计算常量内存中的元素。用 cython 或 pypy 实现这个想法应该会显着提高性能。
尝试一个一个地生成元素是个坏主意,将它们全部保存起来更糟糕。只需要一个元素的值,直接计算即可。
假设您想要的元素位于索引 2**i + k
,其中 k < 2**i
。那么这个元素就是索引k
处元素的否定,索引k
处的元素可以用同样的方式计算。您最终会为所需索引的二进制表示中的每个设置位否定一次元素 0。如果有偶数个设置位,则值为 True。否则,值为 False。