简体   繁体   中英

Algorithm for all permutations of a string in C++ or Python

I need to write a function in c++ or python that gets a string and prints all the options that it can be scrambled. for example - scramble("abc") will print -

abc
acb
bac
bca
cab
cba

Of course it wouldn't be only words that their length is 3.

In Python, you can use the handy permutations function from itertools.

from itertools import permutations

def scrambles(word):
    return [''.join(permutation) for permutation in permutations(word)]

Alternatively, here's a recursive permutation algorithm explicitly spelled out:

def permutations(word):

    if len(word) == 1:
        # the word is one letter long, so this is the base case; there is only one permutation
        return [word]

    # recursively get all permutations of the word after its first letter
    subword_perms = permutations(word[1:])

    # insert the first letter at all possible positions in each of the possible permutations of the rest of the letters
    first_letter = word[0]
    perms = []
    for subword_perm in subword_perms:
        for i in range(len(subword_perm)+1):
            perm = subword_perm[:i] + first_letter + subword_perm[i:]

            # test to make sure permutation wasn't already found (which is possible if some letters are duplicated within the word)
            if perm not in perms:
                perms.append(perm)
    return perms

Here's a shorter recursive function to find all permutations of letters in a string:

def gen_perms(n,text):
    if n == 1:
        return {a for a in text}
    temp = {a + b
           for a in text
           for b in gen_perms(n-1,text)}
    return temp

n is the length of the words/sets you want to generate

text is the set of letters you want to use.

I use sets because they have no duplicate entries; only unique elements.

To explain the algorithm, start with the base case of n=1. This special case is dealt with by returning each of the letters.

    if n == 1:
        return {a for a in text}

Example, when n =1, text ='yz':

>>> perms = gen_perms(1,'yz')
>>> print len(perms)
2
>>> print sorted(perms)
['y', 'z']

When n=2, we recursively run the function, so think about the base case from above being returned on this line:

           {a + b
           for a in text
           for b in gen_perms(n-1,text)}

and adding each possible letter onto that. I'll rewrite it with the text replaced with the values we entered:

           {a + b
           for a in 'yz'
           for b in ['y','z']}

Hopefully you can see that we would get ['yy', 'yz', 'zy', 'zz'] , and we do:

>>> perms = gen_perms(2,'yz')
>>> print len(perms)
4
>>> print sorted(perms)
['yy', 'yz', 'zy', 'zz']

Sets are really nice to use here, because if we change our text to contain repeated letters, they are disregared:

>>> perms = gen_perms(2,'yyyzz')
>>> print len(perms)
4
>>> print sorted(perms)
['yy', 'yz', 'zy', 'zz']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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