Python 如何交错或创建两个字符串的唯一排列(无递归)
问题是打印两个给定字符串的所有可能交错。因此,我用Python编写了一个运行如下的工作代码:Python 如何交错或创建两个字符串的唯一排列(无递归),python,arrays,string,algorithm,complexity-theory,Python,Arrays,String,Algorithm,Complexity Theory,问题是打印两个给定字符串的所有可能交错。因此,我用Python编写了一个运行如下的工作代码: def inter(arr1,arr2,p1,p2,arr): thisarr = copy(arr) if p1 == len(arr1) and p2 == len(arr2): printarr(thisarr) elif p1 == len(arr1): thisarr.extend(arr2[p2:]) printarr(
def inter(arr1,arr2,p1,p2,arr):
thisarr = copy(arr)
if p1 == len(arr1) and p2 == len(arr2):
printarr(thisarr)
elif p1 == len(arr1):
thisarr.extend(arr2[p2:])
printarr(thisarr)
elif p2 == len(arr2):
thisarr.extend(arr1[p1:])
printarr(thisarr)
else:
thisarr.append(arr1[p1])
inter(arr1,arr2,p1+1,p2,thisarr)
del thisarr[-1]
thisarr.append(arr2[p2])
inter(arr1,arr2,p1,p2+1,thisarr)
return
[0] * A + [1] * B
它出现在字符串中的每个点,然后对于一个递归调用,它认为当前元素属于第一个数组,在下一个调用中,它属于另一个数组。因此,如果输入字符串是ab
和cd
,它将打印出abcd
,acbd
,cdab
,cabd
,等等。p1
和p2
是指向数组的指针(因为Python字符串是不可变的,我使用数组!)。有谁能告诉我,这段代码的复杂性是什么,它是否可以改进?我编写了一个类似的代码来打印给定数组中长度k
的所有组合:
def kcomb(arr,i,thisarr,k):
thisarr = copy(thisarr)
j,n = len(thisarr),len(arr)
if n-i<k-j or j >k:
return
if j==k:
printarr(thisarr)
return
if i == n:
return
thisarr.append(arr[i])
kcomb(arr,i+1,thisarr,k)
del thisarr[-1]
kcomb(arr,i+1,thisarr,k)
return
排列
对你有用吗?或者,这是编码实践吗
>>> from itertools import permutations
>>> s1 = "ab"
>>> s2 = "cd"
>>> all_values = [c for c in s1 + s2]
>>> ["".join(r) for r in permutations(all_values)]
['abcd', 'abdc', 'acbd', 'acdb', 'adbc', 'adcb', 'bacd', 'badc', 'bcad', 'bcda', 'bdac', 'bdca', 'cabd', 'cadb', 'cbad', 'cbda', 'cdab', 'cdba', 'dabc', 'dacb', 'dbac', 'dbca', 'dcab', 'dcba']
这就是我认为你想要做的:
from itertools import product, chain
def interleave(a, b):
if len(b) > len(a):
a, b = b, a
boolean = (True, False)
for z in range(len(a) - len(b) + 1):
pairs = list(zip(a[z:], b))
for vector in product(*[boolean] * max(map(len, (a, b)))):
permutation = (pair if i else reversed(pair)
for i, pair in zip(vector, pairs))
yield a[:z] + ''.join(chain.from_iterable(permutation))
您的问题可以简化为创建特定列表的所有唯一排列。假设
A
和B
分别是字符串arr1
和arr2
的长度。然后构建如下列表:
def inter(arr1,arr2,p1,p2,arr):
thisarr = copy(arr)
if p1 == len(arr1) and p2 == len(arr2):
printarr(thisarr)
elif p1 == len(arr1):
thisarr.extend(arr2[p2:])
printarr(thisarr)
elif p2 == len(arr2):
thisarr.extend(arr1[p1:])
printarr(thisarr)
else:
thisarr.append(arr1[p1])
inter(arr1,arr2,p1+1,p2,thisarr)
del thisarr[-1]
thisarr.append(arr2[p2])
inter(arr1,arr2,p1,p2+1,thisarr)
return
[0] * A + [1] * B
从该列表的唯一排列到两个字符串arr1
和arr2
的所有可能交错,存在一对一的对应关系(双射)。其思想是让排列的每个值指定从哪个字符串中提取下一个字符。下面是一个示例实现,展示了如何从排列构造交织:
>>> def make_interleave(arr1, arr2, permutation):
... iters = [iter(arr1), iter(arr2)]
... return "".join(iters[i].next() for i in permutation)
...
>>> make_interleave("ab", "cde", [1, 0, 0, 1, 1])
'cabde'
我在python邮件列表中发现了一个问题,它询问如何有效地解决这个问题。答案建议使用Knuth的《计算机编程的艺术》第4卷第2分册:生成所有排列中描述的算法。我在网上找到了草稿的pdf。本文还介绍了该算法
下面是我自己的next\u permutation
算法的注释实现,作为python生成器函数
def unique_permutations(seq):
"""
Yield only unique permutations of seq in an efficient way.
A python implementation of Knuth's "Algorithm L", also known from the
std::next_permutation function of C++, and as the permutation algorithm
of Narayana Pandita.
"""
# Precalculate the indices we'll be iterating over for speed
i_indices = list(range(len(seq) - 1, -1, -1))
k_indices = i_indices[1:]
# The algorithm specifies to start with a sorted version
seq = sorted(seq)
while True:
yield seq
# Working backwards from the last-but-one index, k
# we find the index of the first decrease in value. 0 0 1 0 1 1 1 0
for k in k_indices:
if seq[k] < seq[k + 1]:
break
else:
# Introducing the slightly unknown python for-else syntax:
# else is executed only if the break statement was never reached.
# If this is the case, seq is weakly decreasing, and we're done.
return
# Get item from sequence only once, for speed
k_val = seq[k]
# Working backwards starting with the last item, k i
# find the first one greater than the one at k 0 0 1 0 1 1 1 0
for i in i_indices:
if k_val < seq[i]:
break
# Swap them in the most efficient way
(seq[k], seq[i]) = (seq[i], seq[k]) # k i
# 0 0 1 1 1 1 0 0
# Reverse the part after but not k
# including k, also efficiently. 0 0 1 1 0 0 1 1
seq[k + 1:] = seq[-1:k:-1]
def唯一排列(seq):
"""
以有效的方式只产生seq的唯一置换。
Knuth的“算法L”的python实现,也称为
{STD::C++的NExtx置换函数,作为置换算法
纳拉亚纳·潘迪塔。
"""
#预先计算我们将迭代的速度指数
i_索引=列表(范围(len(seq)-1,-1,-1))
k_指数=i_指数[1:]
#算法指定从排序版本开始
seq=已排序(seq)
尽管如此:
收益率序列
#从上一个索引(但只有一个)向后工作,k
#我们找到了值第一次下降的指数。0 1 0
对于k in k_指数:
如果seq[k]
根据问题,算法的每一个收益率都有一个O(1)的摊销复杂度,但根据下面评论的rici,只有当所有数字都是唯一的情况下才会出现这种情况,而在这种情况下它们肯定不是唯一的
在任何情况下,收益率的数量为时间复杂度提供了一个下限,它由
(A + B)! / (A! * B!)
(A+B)!/(A!*B!)
然后,为了找到实时复杂度,我们需要将每个成品的平均复杂度与基于排列构造结果字符串的复杂度相加。如果我们用上面的公式乘以这个和,我们就得到了总的时间复杂度。好的,在做了一些工作之后,我们从其他答案中得到建议。主要是懒汉。(现在已将其转换为一个类)uuu all_uperms来自: 此外,您还可以访问类成员,如:
>>> inter = Interleave(A, B)
>>> inter.results
['abcdef', 'abdcef', 'abdecf', 'abdefc', 'adbcef', 'adbecf', 'adbefc', 'adebcf', 'adebfc', 'adefbc', 'dabcef', 'dabecf', 'dabefc', 'daebcf', 'daebfc', 'daefbc', 'deabcf', 'deabfc', 'deafbc', 'defabc']
>>> inter.A
['a', 'b', 'c']
>>> inter.B
['d', 'e', 'f']
你可以发布“printarr”的代码吗?是的,我可以,但这很简单,它只是将数组作为输入,将所有元素连接成字符串并打印出来!很难理解你在做什么。你能发布输入和预期输出吗?如果我理解正确-你有两个字符串,你想看到所有的组合使用每个字符串中的所有字符,你可以做?例如,您有两个字符数组,并且希望以各种可能的方式组合它们。也就是说,你有一个项目列表,你想找到各种方法来组合它们?几乎,但保留单个字符串的顺序。也就是说,如果string1是
abcd
,string2是efgh
,那么在交错字符串中,a'应该在b之前,它应该在c之前,它应该在d`之前。在这两者之间,string2中的字符应该适合,但在相同的条件下,保留单个字母的顺序。不,不,我正在尝试开发一个工作代码,而不使用这些内置函数。另外,您的输出不正确,在许多输出字符串中,b
出现
>>> inter = Interleave(A, B)
>>> inter.results
['abcdef', 'abdcef', 'abdecf', 'abdefc', 'adbcef', 'adbecf', 'adbefc', 'adebcf', 'adebfc', 'adefbc', 'dabcef', 'dabecf', 'dabefc', 'daebcf', 'daebfc', 'daefbc', 'deabcf', 'deabfc', 'deafbc', 'defabc']
>>> inter.A
['a', 'b', 'c']
>>> inter.B
['d', 'e', 'f']