在python中查找给定字符串的所有可能排列
我有一根绳子。我想通过改变字符串中字符的顺序,从该字符串生成所有排列。比如说:在python中查找给定字符串的所有可能排列,python,string,permutation,Python,String,Permutation,我有一根绳子。我想通过改变字符串中字符的顺序,从该字符串生成所有排列。比如说: x='stack' 我想要的是这样一份清单 l=['stack','satck','sackt'.......] 目前,我正在迭代字符串的列表类型,随机选取2个字母,将它们转换为一个新字符串,并将其添加到l的集合类型中。根据字符串的长度,我正在计算可能的置换次数,并继续迭代,直到集合大小达到极限。 必须有更好的方法来做到这一点 请参见或。itertools模块有一个名为置换()的有用方法。说: itertools
x='stack'
我想要的是这样一份清单
l=['stack','satck','sackt'.......]
目前,我正在迭代字符串的列表类型,随机选取2个字母,将它们转换为一个新字符串,并将其添加到l的集合类型中。根据字符串的长度,我正在计算可能的置换次数,并继续迭代,直到集合大小达到极限。
必须有更好的方法来做到这一点 请参见或。itertools模块有一个名为置换()的有用方法。说: itertools.置换(iterable[,r]) 返回iterable中元素的连续r长度置换 如果未指定r或r为None,则r默认为 生成iterable和所有可能的全长置换 排列按字典排序顺序发出。因此,如果输入 iterable排序后,排列元组将以排序方式生成 秩序 不过,您必须将排列的字母作为字符串连接起来
>>> from itertools import permutations
>>> perms = [''.join(p) for p in permutations('stack')]
>>> perms
['stack'、'stakc'、'stcak'、'stcka'、'stkac'、'stkca'、'satck',
“satkc”、“sactk”、“SAKT”、“saktc”、“sakct”、“sctak”、“sctka”,
“scatk”、“scakt”、“sckta”、“sckat”、“sktac”、“sktca”、“skatc”,
“skact”、“skcta”、“skcat”、“tsack”、“tsakc”、“tscak”、“tscka”,
‘tskac’、‘tskca’、‘tasck’、‘taskc’、‘tacsk’、‘tacks’、‘taksc’,
“takcs”、“tcsak”、“tcska”、“tcask”、“tcaks”、“tcksa”、“tckas”,
‘tksac’、‘tksca’、‘tkasc’、‘tkacs’、‘tkcsa’、‘tkcas’、‘astck’,
“astkc”、“asctk”、“asckt”、“asktc”、“askct”、“atsck”、“atskc”,
“atcsk”、“atcks”、“atksc”、“atkcs”、“acstk”、“acskt”、“actsk”,
“actks”、“ackst”、“ackts”、“akstc”、“aksct”、“aktsc”、“aktcs”,
‘akcst’、‘akcts’、‘cstak’、‘cstka’、‘csatk’、‘csakt’、‘cskta’,
“cskat”、“ctsak”、“ctska”、“ctask”、“ctaks”、“ctksa”、“ctkas”,
‘卡斯克’、‘卡斯克’、‘卡斯克’、‘卡克斯特’、‘卡克斯特’、‘卡克斯特’、‘卡斯塔’,
‘cksat’、‘cktsa’、‘cktas’、‘ckast’、‘ckats’、‘kstac’、‘kstca’,
“ksatc”、“ksact”、“kscta”、“kscat”、“ktsac”、“ktsca”、“ktasc”,
“ktacs”、“ktcsa”、“ktcas”、“kastc”、“kasct”、“katsc”、“katcs”,
‘kacst’、‘kacts’、‘kcsta’、‘kcsat’、‘kctsa’、‘kctas’、‘kcast’,
“kcats”]
如果您发现自己受到重复数据的困扰,请尝试将数据装配到一个没有重复数据的结构中,如集合
:
>>> perms = [''.join(p) for p in permutations('stacks')]
>>> len(perms)
720
>>> len(set(perms))
360
感谢@pst指出这不是我们传统上认为的类型转换,而是对
set()
构造函数的调用。您可以得到所有N!没有太多代码的置换
def permutations(string, step = 0):
# if we've gotten to the end, print the permutation
if step == len(string):
print "".join(string)
# everything to the right of step has not been swapped yet
for i in range(step, len(string)):
# copy the string (store as array)
string_copy = [character for character in string]
# swap the current index with the step
string_copy[step], string_copy[i] = string_copy[i], string_copy[step]
# recurse on the portion of the string that has not been swapped yet (now it's index will begin with step + 1)
permutations(string_copy, step + 1)
下面是一个稍微改进的版本的代码,用于返回字符串
s
的所有排列的列表,其中包含不同的字符(不一定按字典排序顺序),而不使用itertools:
def get_perms(s, i=0):
"""
Returns a list of all (len(s) - i)! permutations t of s where t[:i] = s[:i].
"""
# To avoid memory allocations for intermediate strings, use a list of chars.
if isinstance(s, str):
s = list(s)
# Base Case: 0! = 1! = 1.
# Store the only permutation as an immutable string, not a mutable list.
if i >= len(s) - 1:
return ["".join(s)]
# Inductive Step: (len(s) - i)! = (len(s) - i) * (len(s) - i - 1)!
# Swap in each suffix character to be at the beginning of the suffix.
perms = get_perms(s, i + 1)
for j in range(i + 1, len(s)):
s[i], s[j] = s[j], s[i]
perms.extend(get_perms(s, i + 1))
s[i], s[j] = s[j], s[i]
return perms
你为什么不简单地做:
from itertools import permutations
perms = [''.join(p) for p in permutations(['s','t','a','c','k'])]
print perms
print len(perms)
print len(set(perms))
正如您所看到的,您不会得到任何副本:
['stack', 'stakc', 'stcak', 'stcka', 'stkac', 'stkca', 'satck', 'satkc',
'sactk', 'sackt', 'saktc', 'sakct', 'sctak', 'sctka', 'scatk', 'scakt', 'sckta',
'sckat', 'sktac', 'sktca', 'skatc', 'skact', 'skcta', 'skcat', 'tsack',
'tsakc', 'tscak', 'tscka', 'tskac', 'tskca', 'tasck', 'taskc', 'tacsk', 'tacks',
'taksc', 'takcs', 'tcsak', 'tcska', 'tcask', 'tcaks', 'tcksa', 'tckas', 'tksac',
'tksca', 'tkasc', 'tkacs', 'tkcsa', 'tkcas', 'astck', 'astkc', 'asctk', 'asckt',
'asktc', 'askct', 'atsck', 'atskc', 'atcsk', 'atcks', 'atksc', 'atkcs', 'acstk',
'acskt', 'actsk', 'actks', 'ackst', 'ackts', 'akstc', 'aksct', 'aktsc', 'aktcs',
'akcst', 'akcts', 'cstak', 'cstka', 'csatk', 'csakt', 'cskta', 'cskat', 'ctsak',
'ctska', 'ctask', 'ctaks', 'ctksa', 'ctkas', 'castk', 'caskt', 'catsk', 'catks',
'cakst', 'cakts', 'cksta', 'cksat', 'cktsa', 'cktas', 'ckast', 'ckats', 'kstac',
'kstca', 'ksatc', 'ksact', 'kscta', 'kscat', 'ktsac', 'ktsca', 'ktasc', 'ktacs',
'ktcsa', 'ktcas', 'kastc', 'kasct', 'katsc', 'katcs', 'kacst', 'kacts', 'kcsta',
'kcsat', 'kctsa', 'kctas', 'kcast', 'kcats']
120
120
[Finished in 0.3s]
这是一个简单而直接的递归实现
def stringPermutations(s):
if len(s) < 2:
yield s
return
for pos in range(0, len(s)):
char = s[pos]
permForRemaining = list(stringPermutations(s[0:pos] + s[pos+1:]))
for perm in permForRemaining:
yield char + perm
def字符串置换:
如果长度小于2:
产量
返回
对于范围(0,len)内的位置:
char=s[pos]
permForRemaining=list(stringPermutations(s[0:pos]+s[pos+1:]))
对于perm中的perm ForRemaining:
产炭+烫发
这里是另一种不同于@Adriano和@Illerucs发布的方法。这有一个更好的运行时间,您可以通过测量时间来检查自己:
def removeCharFromStr(str, index):
endIndex = index if index == len(str) else index + 1
return str[:index] + str[endIndex:]
# 'ab' -> a + 'b', b + 'a'
# 'abc' -> a + bc, b + ac, c + ab
# a + cb, b + ca, c + ba
def perm(str):
if len(str) <= 1:
return {str}
permSet = set()
for i, c in enumerate(str):
newStr = removeCharFromStr(str, i)
retSet = perm(newStr)
for elem in retSet:
permSet.add(c + elem)
return permSet
def removeCharFromStr(str,index):
endIndex=index如果index==len(str)else index+1
返回str[:index]+str[endIndex:]
#“ab”->a+“b”,b+“a”
#‘abc’->a+bc、b+ac、c+ab
#a+cb、b+ca、c+ba
def perm(str):
如果len(str)这里有一个简单的函数返回唯一排列:
def permutations(string):
if len(string) == 1:
return string
recursive_perms = []
for c in string:
for perm in permutations(string.replace(c,'',1)):
revursive_perms.append(c+perm)
return set(revursive_perms)
下面是一个非常简单的生成器版本:
def find_all_permutations(s, curr=[]):
if len(s) == 0:
yield curr
else:
for i, c in enumerate(s):
for combo in find_all_permutations(s[:i]+s[i+1:], curr + [c]):
yield "".join(combo)
我觉得还不错 itertools.permutations
很好,但它不能很好地处理包含重复元素的序列。这是因为它在内部渗透了序列索引,而忽略了序列项的值
当然,可以通过一个集合过滤itertools.permutations
的输出以消除重复项,但生成这些重复项仍然会浪费时间,如果基序列中有多个重复元素,则会有大量重复项。此外,使用集合保存结果会浪费RAM,这首先否定了使用迭代器的好处
幸运的是,还有更有效的方法。下面的代码使用了14世纪印度数学家Narayana Pandita的算法,可以在。这个古老的算法仍然是已知的按顺序生成排列的最快方法之一,而且它非常健壮,因为它能够正确处理包含重复元素的排列
def lexico_permute_string(s):
''' Generate all permutations in lexicographic order of string `s`
This algorithm, due to Narayana Pandita, is from
https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
To produce the next permutation in lexicographic order of sequence `a`
1. Find the largest index j such that a[j] < a[j + 1]. If no such index exists,
the permutation is the last permutation.
2. Find the largest index k greater than j such that a[j] < a[k].
3. Swap the value of a[j] with that of a[k].
4. Reverse the sequence from a[j + 1] up to and including the final element a[n].
'''
a = sorted(s)
n = len(a) - 1
while True:
yield ''.join(a)
#1. Find the largest index j such that a[j] < a[j + 1]
for j in range(n-1, -1, -1):
if a[j] < a[j + 1]:
break
else:
return
#2. Find the largest index k greater than j such that a[j] < a[k]
v = a[j]
for k in range(n, j, -1):
if v < a[k]:
break
#3. Swap the value of a[j] with that of a[k].
a[j], a[k] = a[k], a[j]
#4. Reverse the tail of the sequence
a[j+1:] = a[j+1:][::-1]
for s in lexico_permute_string('data'):
print(s)
当然,如果您想将生成的字符串收集到一个列表中,您可以这样做
list(lexico_permute_string('data'))
或者在最新的Python版本中:
[*lexico_permute_string('data')]
这是使用递归生成置换的一种方法,通过将字符串“a”、“ab”和“abc”作为输入,您可以轻松理解代码
你得到了所有的N!堆栈溢出用户已经发布了一些强大的解决方案,但我想展示另一个解决方案。我觉得这个更直观
其思想是,对于给定的字符串:我们可以通过算法(伪代码)递归:
排列=字符+字符串中字符的排列(字符串-字符)
我希望它能帮助别人
def permutations(string):
"""
Create all permutations of a string with non-repeating characters
"""
permutation_list = []
if len(string) == 1:
return [string]
else:
for char in string:
[permutation_list.append(char + a) for a in permutations(string.replace(char, "", 1))]
return permutation_list
每个人都喜欢自己代码的味道。分享我发现最简单的一个:
def get_permutations(word):
if len(word) == 1:
yield word
for i, letter in enumerate(word):
for perm in get_permutations(word[:i] + word[i+1:]):
yield letter + perm
该计划不会消除重复项,但我认为这是最有效的方法之一:
s=raw_input("Enter a string: ")
print "Permutations :\n",s
size=len(s)
lis=list(range(0,size))
while(True):
k=-1
while(k>-size and lis[k-1]>lis[k]):
k-=1
if k>-size:
p=sorted(lis[k-1:])
e=p[p.index(lis[k-1])+1]
lis.insert(k-1,'A')
lis.remove(e)
lis[lis.index('A')]=e
lis[k:]=sorted(lis[k:])
list2=[]
for k in lis:
list2.append(s[k])
print "".join(list2)
else:
break
下面是另一种使用基于的最小代码进行字符串排列的方法。
我们基本上创建一个循环,然后一次交换两个字符,
在回路内部,我们将有
def permute(seq):
if not seq:
yield seq
else:
for i in range(len(seq)):
rest = seq[:i]+seq[i+1:]
for x in permute(rest):
yield seq[i:i+1]+x
print(list(permute('stack')))
def perm(string):
res=[]
for j in range(0,len(string)):
if(len(string)>1):
for i in perm(string[1:]):
res.append(string[0]+i)
else:
return [string];
string=string[1:]+string[0];
return res;
l=set(perm("abcde"))
def permutations(string):
"""
Create all permutations of a string with non-repeating characters
"""
permutation_list = []
if len(string) == 1:
return [string]
else:
for char in string:
[permutation_list.append(char + a) for a in permutations(string.replace(char, "", 1))]
return permutation_list
def get_permutations(word):
if len(word) == 1:
yield word
for i, letter in enumerate(word):
for perm in get_permutations(word[:i] + word[i+1:]):
yield letter + perm
s=raw_input("Enter a string: ")
print "Permutations :\n",s
size=len(s)
lis=list(range(0,size))
while(True):
k=-1
while(k>-size and lis[k-1]>lis[k]):
k-=1
if k>-size:
p=sorted(lis[k-1:])
e=p[p.index(lis[k-1])+1]
lis.insert(k-1,'A')
lis.remove(e)
lis[lis.index('A')]=e
lis[k:]=sorted(lis[k:])
list2=[]
for k in lis:
list2.append(s[k])
print "".join(list2)
else:
break
def permute(data, i, length):
if i==length:
print(''.join(data) )
else:
for j in range(i,length):
#swap
data[i], data[j] = data[j], data[i]
permute(data, i+1, length)
data[i], data[j] = data[j], data[i]
string = "ABC"
n = len(string)
data = list(string)
permute(data, 0, n)
def permute_all_chars(list, begin, end):
if (begin == end):
print(list)
return
for current_position in range(begin, end + 1):
list[begin], list[current_position] = list[current_position], list[begin]
permute_all_chars(list, begin + 1, end)
list[begin], list[current_position] = list[current_position], list[begin]
given_str = 'ABC'
list = []
for char in given_str:
list.append(char)
permute_all_chars(list, 0, len(list) -1)
from itertools import permutations
def stringPermutate(s1):
length=len(s1)
if length < 2:
return s1
perm = [''.join(p) for p in permutations(s1)]
return set(perm)
# for a string with length n, there is a factorial n! permutations
alphabet = 'abc'
starting_perm = ''
# with recursion
def premuate(perm, alphabet):
if not alphabet: # we created one word by using all letters in the alphabet
print(perm + alphabet)
else:
for i in range(len(alphabet)): # iterate over all letters in the alphabet
premuate(perm + alphabet[i], alphabet[0:i] + alphabet[i+1:]) # chose one letter from the alphabet
# call it
premuate(starting_perm, alphabet)
abc
acb
bac
bca
cab
cba
# swap ith and jth character of string
def swap(s, i, j):
q = list(s)
q[i], q[j] = q[j], q[i]
return ''.join(q)
# recursive function
def _permute(p, s, permutes):
if p >= len(s) - 1:
permutes.append(s)
return
for i in range(p, len(s)):
_permute(p + 1, swap(s, p, i), permutes)
# helper function
def permute(s):
permutes = []
_permute(0, s, permutes)
return permutes
# TEST IT
s = "1234"
all_permute = permute(s)
print(all_permute)
# swap ith and jth character of string
def swap(s, i, j):
q = list(s)
q[i], q[j] = q[j], q[i]
return ''.join(q)
# iterative function
def permute_using_stack(s):
stk = [(0, s)]
permutes = []
while len(stk) > 0:
p, s = stk.pop(0)
if p >= len(s) - 1:
permutes.append(s)
continue
for i in range(p, len(s)):
stk.append((p + 1, swap(s, p, i)))
return permutes
# TEST IT
s = "1234"
all_permute = permute_using_stack(s)
print(all_permute)
# swap ith and jth character of string
def swap(s, i, j):
q = list(s)
q[i], q[j] = q[j], q[i]
return ''.join(q)
# finds next lexicographic string if exist otherwise returns -1
def next_lexicographical(s):
for i in range(len(s) - 2, -1, -1):
if s[i] < s[i + 1]:
m = s[i + 1]
swap_pos = i + 1
for j in range(i + 1, len(s)):
if m > s[j] > s[i]:
m = s[j]
swap_pos = j
if swap_pos != -1:
s = swap(s, i, swap_pos)
s = s[:i + 1] + ''.join(sorted(s[i + 1:]))
return s
return -1
# helper function
def permute_lexicographically(s):
s = ''.join(sorted(s))
permutes = []
while True:
permutes.append(s)
s = next_lexicographical(s)
if s == -1:
break
return permutes
# TEST IT
s = "1234"
all_permute = permute_lexicographically(s)
print(all_permute)
import math
def getFactors(root,num):
sol = []
# return condition
if len(num) == 1:
return [root+num]
# looping in next iteration
for i in range(len(num)):
# Creating a substring with all remaining char but the taken in this iteration
if i > 0:
rem = num[:i]+num[i+1:]
else:
rem = num[i+1:]
# Concatenating existing solutions with the solution of this iteration
sol = sol + getFactors(root + num[i], rem)
return sol
inpt = "1234"
results = getFactors("",inpt)
if len(results) == math.factorial(len(inpt)) | len(results) != len(set(results)):
print("Wrong approach")
else:
print("Correct Approach")
def permute(word):
if len(word) == 1:
return [word]
permutations = permute(word[1:])
character = word[0]
result = []
for p in permutations:
for i in range(len(p)+1):
result.append(p[:i] + character + p[i:])
return result
running code.
>>> permute('abc')
['abc', 'bac', 'bca', 'acb', 'cab', 'cba']
vow ="aeiou"
lsword=[]
ta=[]
for a in range(1,len(s)+1):
t=list(itertools.permutations(s,a))
lsword.append(t)
for i in range(0,len(lsword)):
for xa in lsword[i]:
if vow.startswith(xa):
ta.append("".join(xa))
print(ta)