这是我想出的代码:
def combinations(input):
ret = ['']
for i in range(len(input)):
ret.extend([prefix+input[i] for prefix in ret])
return ret
这个算法是O(2^n)时间,但是空间可以减少吗?我听说 usingyield
可能有效,但在思考如何使用yield
. 请不要使用内置的组合功能——我想看看它是如何实现的。
这是我想出的代码:
def combinations(input):
ret = ['']
for i in range(len(input)):
ret.extend([prefix+input[i] for prefix in ret])
return ret
这个算法是O(2^n)时间,但是空间可以减少吗?我听说 usingyield
可能有效,但在思考如何使用yield
. 请不要使用内置的组合功能——我想看看它是如何实现的。
您的问题明确表示您想查看代码的外观,因此这里是 O(n) 空间解决方案的手动编码示例:
def combinations(input_list, acc=''):
if not input_list:
yield acc
return
next_val = input_list[0]
for rest in combinations(input_list[1:], acc):
yield rest
acc += next_val
# In python 3.2, you can use "yield from combinations(input_list[1:], acc)"
for rest in combinations(input_list[1:], acc):
yield rest
请注意,子字符串算术可能很昂贵(因为它必须多次复制字符串),因此在复杂性方面,这里有一个更有效的版本:
def combinations(input_list, acc='', from_idx=0):
if len(input_list) <= from_idx:
yield acc
return
next_val = input_list[from_idx]
for rest in combinations(input_list, acc, from_idx + 1):
yield rest
acc += next_val
# In python 3.2, you can use "yield from combinations(input_list[1:], acc)"
for rest in combinations(input_list, acc, from_idx + 1):
yield rest
我没有使用 Python 3.2,但如果你是,你可以这样写:
def combinations(input_list, acc='', from_idx=0):
if len(input_list) <= from_idx:
yield acc
return
next_val = input_list[from_idx]
yield from combinations(input_list, acc, from_idx + 1)
acc += next_val
yield from combinations(input_list, acc, from_idx + 1)
我还应该注意,这纯粹是学术性itertools.combinations
的,因为它做得很好并且适用于更广泛的输入(包括生成器表达式)。
You can use yield
in your code like so:
def combinations(input):
ret = ['']
yield ''
for i in range(len(input)):
for prefix in ret:
combination = prefix+input[i]
ret.extend(combination)
yield combination
But it doesn't save you any space.
The itertools.combinations documentation shows a (much) more complicated algorithm that works in constant space - the actual implementation is in C, but claims to be equivalent.
这样的事情应该这样做:
>>> print list(itertools.combinations({1, 2, 3, 4}, 3))
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
>>>