简体   繁体   English

仅通过一次交换,如何找到字符串的所有可能排列?

[英]How do I find all possible permutations of a string with only single swap?

The complexity should be O(n) where n is length of string. 复杂度应为O(n),其中n是字符串的长度。 Ex: For 'abc', answer is 'bac', 'cba', 'acb'. 例如:对于“ abc”,答案是“ bac”,“ cba”,“ acb”。 'bca' and 'cab' should not be in the list as two swaps are required to convert it to 'abc'. “ bca”和“ cab”不应在列表中,因为需要两次交换才能将其转换为“ abc”。

I have made a O(n 2 ) algorithm but it is very slow. 我做了一个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)

The number of possible outcomes for a string (with distinct characters) of length n is nC2 = n * (n-1) / 2 , since we can choose two letters at any two indices and swap them. 长度为n的字符串(具有不同字符)的可能结果nnC2 = n * (n-1) / 2 ,因为我们可以在任意两个索引处选择两个字母并将它们交换。

Hence, if you plan to print all of the outcomes, the complexity will be O(n^2) and a O(n) solution is not possible. 因此,如果您计划打印所有结果,则复杂度将为O(n^2)并且不可能使用O(n)解决方案。

For duplicate characters, the reasoning becomes more complex. 对于重复的字符,推理变得更加复杂。 Suppose there is exactly one duplicate character repeated k times. 假设恰好有一个重复的字符重复k次。 Then there are nk swaps that will be identical. 然后有nk交换将是相同的。 So if there is exactly one character repeated, and it is repeated k times, the number of possibilities is nC2 - (nk) . 因此,如果恰好有一个字符重复,并且重复了k次,则可能性数为nC2 - (nk) This can be extended to more repeated characters using the inclusion-exclusion principle. 使用包含-排除原理,可以将此扩展到更多重复的字符。

Use itertools.combinations to find all possible combination of two char index, then swapped it. 使用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')

The above code will give you the correct result: 上面的代码将为您提供正确的结果:

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

Hope it helps! 希望能帮助到你!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM