如何只用单个交换找到字符串的所有可能排列?

时间:2016-03-07 07:12:44

标签: python string algorithm permutation

复杂度应该是O(n),其中n是字符串的长度。 例如:对于'abc',答案是'bac','cba','acb'。 'bca'和'cab'不应该在列表中,因为需要两个掉期才能将其转换为'abc'。

我做了一个O(n 2 )算法,但速度很慢。

def f(s):
    temp=list(s)
    l=[]
    for i in range(len(s)):
        for j in range(len(s)):
            temp=list(s)
            temp[i],temp[j]=temp[j],temp[i]
            l.append("".join(str(i) for i in temp))
    print set(l)

2 个答案:

答案 0 :(得分:3)

长度为n的字符串(具有不同字符)的可能结果数为nC2 = n * (n-1) / 2,因为我们可以在任意两个索引处选择两个字母并进行交换。

因此,如果您打算打印所有结果,则复杂性将为O(n^2),并且无法使用O(n)解决方案。

对于重复的字符,推理变得更加复杂。假设只有一个重复字符重复k次。然后有n-k个互换将是相同的。因此,如果只重复了一个字符,并且重复k次,则可能性的数量为nC2 - (n-k)。这可以使用包含 - 排除原则扩展到更多重复的字符。

答案 1 :(得分:1)

使用itertools.combinations查找两个char索引的所有可能组合,然后交换它。

# -*- coding: utf-8 -*-
import itertools


def f(s):
    result = []
    # This will produce: [0, 1], [0, 2], [1, 2]
    for idx1, idx2 in itertools.combinations(range(len(s)), 2):
        swapped_s = list(s)
        swapped_s[idx1], swapped_s[idx2] = swapped_s[idx2], swapped_s[idx1]
        result.append(''.join(swapped_s))
    return result

if __name__ == '__main__':
    print f('abc')

上面的代码会给你正确的结果:

['bac', 'cba', 'acb']

希望它有所帮助!