我试图生成字符串的所有可能排列,如" 0000011111"或" 000 11 2222 333"。我尝试在" 0000011111"上使用 itertools 中的排列;像这样:
from itertools import permutations
basestring = "0"*5 +"1"*5
perms = [''.join(p) for p in permutations(basestring)]
print(len(perms), perms)
print(len(set(perms)), set(perms))
但是,当只有10个C 5 = 252 排列时,烫发列表 300万个条目。
我可以使用哪种内置工具更好地处理包含许多重复字符的字符串的排列?
否则该算法如何生成排列(对于" 0000 1111 222")?
Start with 2 characters "0000 1111"
Move right most 0 over one "0001 0111" and add it to the list
Continue moving it to the end "0001 1011" -> "0001 1101" -> "0001 1110"
Now move the next 0 over one "0010 0111" -> "0010 1011"
...
Until you get to "1111 0000".
Then for each of the strings generated, repeat the process with 2's.
222 xxxx xxxx -> 22x 2xxx xxxx -> 22x x2xx xxx...
或者我最好只做set(烫发)来摆脱重复? (我需要用3-5个字符排列20个字符列表,其中itertools排列会给我10e18个字符串)
我已经随便编程了3年,但只知道有一个学期的编程课程的人。
答案 0 :(得分:0)
首先让我们看看你的第一个例子。
from itertools import permutations
basestring = "0"*5 +"1"*5
这给出了basestring = [0000011111]
调用不带任何参数的置换(basestring)将给出n位置字符串长度n的所有排列,这只是n!对于n = 10,这确实是一个很大的数字。这真的是你想要的吗?
接下来,如果您要查找此长度为5的字符串的排列,则需要在对itertools.permutations的调用中指定长度为5。
perms = [''.join(p) for p in permutations(basestring,5)]
这将返回 position 中basetring中所有字符的长度为5的所有排列,而不是值。所以你会得到一些重复。
如itertools.permutations文档see Python 2 version here中所述,该函数返回的长度为n的字符串上的长度为r的排列数将为
N!/(N-R)!或者在这种情况下30240对于n = 10,r = 5。
如果要删除重复项,可以执行
set(perms)
由此返回的组合的数量将是len(set(perms))= 2 ^ 5或32.这是长度为k的字符串的数量,其可以由长度为n的“字母”形成,这是N R个ķ。 “alphabet”是你的basetring中的唯一字符 - 其中有2个(0和1),因此你可以形成32个长度为5的唯一字符串。
答案 1 :(得分:0)
我不确定这是多么有效,但您可以尝试以下方式:
map = ['0','1','2','3']
perms = []
def multisetPerms(s,result):
if all(v is 0 for v in s):
perms.append(result)
return
for i in xrange(len(s)):
if s[i] > 0:
_s = s[:]
_s[i] = _s[i] - 1
multisetPerms(_s,result + map[i])
multisetPerms([3,2,4],'') # 9!/(3!*2!*4!) = 1260
print (len(perms), perms[0:10])
输出:
(1260, ['000112222', '000121222', '000122122', '000122212', '000122221'
, '000211222', '000212122', '000212212', '000212221', '000221122'])