没有 itertools 的两个值的排列(使用递归!)
Posted
技术标签:
【中文标题】没有 itertools 的两个值的排列(使用递归!)【英文标题】:Permutations without itertools for two values (using recursion!) 【发布时间】:2021-08-01 22:10:29 【问题描述】:***,我再次寻求您的帮助。
我知道还有其他关于此的主题,但我会解释是什么让我的作业与众不同。
基本上,我的函数会得到一个 0 和 1 的列表,并返回字符串的所有可能顺序。例如对于“0111”,我们将得到“0111”、“1011”、“1101”、“1110”。
这是我的代码:
def permutations(string):
if len(string) == 1:
return [string]
lst = []
for j in range(len(string)):
remaining_elements = ''.join([string[i] for i in range(len(string)) if i != j])
mini_perm = permutations(remaining_elements)
for perm in mini_perm:
new_str = string[j] + perm
if new_str not in lst:
lst.append(new_str)
return lst
问题是当我运行像“000000000011”这样的字符串时,需要很长时间来处理。应该有一种更有效的方法来做到这一点,因为它只有两个数字。所以我不应该使用索引?
如果您能找到更有效的说法,请帮助我。
(我可以使用循环,但也必须使用递归!)
【问题讨论】:
您可以随时查看itertools
源代码以了解它是如何实现的,如果您不想使用该模块,请执行类似的操作。 docs.python.org/3/library/itertools.html#itertools.permutations
@PacketLoss itertools permutations 函数比我写的自定义版本还要慢,因为它会重复相似的对象。这在基本的 Python 中应该是可能的——递归、for、循环,没有 OOP。
您的示例“000000000011”是否应该返回01 and 10
?
@PacketLoss 它应该返回“000000000011”、“000000000101”、“000000001001”等。
【参考方案1】:
下面是一个使用更有效的递归创建排列的示例:
def permute(string):
string = list(string)
n = len(string)
# Base conditions
# If length is 0 or 1, there is only 1 permutation
if n in [0, 1]:
return [string]
# If length is 2, then there are only two permutations
# Example: [1,2] and [2,1]
if n == 2:
return [string, string[::-1]]
res = []
# For every number in array, choose 1 number and permute the remaining
# by calling permute recursively
for i in range(n):
permutations = permute(string[:i] + string[i+1:])
for p in permutations:
res.append([''.join(str(n) for n in [string[i]] + p)])
return res
这也适用于permute('000000000011')
- 希望对您有所帮助!
【讨论】:
【参考方案2】:您还可以将collections.Counter
与递归生成器函数一起使用:
from collections import Counter
def permute(d):
counts = Counter(d)
def get_permuations(c, s = []):
if len(s) == sum(counts.values()):
yield ''.join(s)
else:
for a, b in c.items():
for i in range(1, b+1):
yield from get_permuations(**c, a:b - i, s+([a]*i))
return list(set(get_permuations(counts)))
print(permute("0111"))
print(permute("000000000011"))
输出:
['0111', '1110', '1101', '1011']
['010000100000', '100000000001', '010000001000', '000000100001', '011000000000', '100000000010', '001001000000', '000000011000', '100000001000', '100000100000', '100001000000', '001000100000', '100010000000', '000000001100', '000100000100', '010010000000', '000000000011', '000000100010', '101000000000', '110000000000', '100000010000', '000100001000', '000001001000', '000000000101', '000000100100', '010000000001', '001000000100', '001000000010', '000110000000', '000011000000', '000001100000', '000000110000', '001000000001', '000010001000', '000100100000', '000001000001', '000010000001', '001100000000', '000100000001', '001000001000', '010000000100', '010000010000', '000000010001', '001000010000', '010001000000', '100000000100', '100100000000', '000000001001', '010100000000', '000010100000', '010000000010', '000000001010', '000010000100', '001010000000', '000000010010', '000001000010', '000100000010', '000101000000', '000000010100', '000100010000', '000000000110', '000001000100', '000010010000', '000000101000', '000001010000', '000010000010']
【讨论】:
【参考方案3】:发布某人给我的答案。感谢您的回复!:
def permutations(zeroes, ones, lst, perm):
if zeroes == 0 and ones == 0:
lst.append(perm)
return
elif zeroes < 0 or ones < 0:
return
permutations(zeroes - 1, ones, lst, perm + '0')
permutations(zeroes, ones - 1, lst, perm + '1')
【讨论】:
以上是关于没有 itertools 的两个值的排列(使用递归!)的主要内容,如果未能解决你的问题,请参考以下文章