Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding all the unique permutations of a string without generating duplicates

Tags:

Finding all the permutations of a string is by a well known Steinhaus–Johnson–Trotter algorithm. But if the string contains the repeated characters such as
AABB,
then the possible unique combinations will be 4!/(2! * 2!) = 6

One way of achieving this is that we can store it in an array or so and then remove the duplicates.

Is there any simpler way to modify the Johnson algorithm, so that we never generate the duplicated permutations. (In the most efficient way)

like image 318
titan Avatar asked Feb 09 '12 20:02

titan


People also ask

How do you calculate unique permutations?

The number of permutations of n distinct objects, taken r at a time is: Pr = n! / (n - r)! Thus, 210 different 3-digit numbers can be formed from the digits 1, 2, 3, 4, 5, 6, and 7.


2 Answers

First convert the string to a set of unique characters and occurrence numbers e.g. BANANA -> (3, A),(1,B),(2,N). (This could be done by sorting the string and grouping letters). Then, for each letter in the set, prepend that letter to all permutations of the set with one less of that letter (note the recursion). Continuing the "BANANA" example, we have: permutations((3,A),(1,B),(2,N)) = A:(permutations((2,A),(1,B),(2,N)) ++ B:(permutations((3,A),(2,N)) ++ N:(permutations((3,A),(1,B),(1,N))

Here is a working implementation in Haskell:

circularPermutations::[a]->[[a]]
circularPermutations xs = helper [] xs []
                          where helper acc [] _ = acc
                                helper acc (x:xs) ys =
                                  helper (((x:xs) ++ ys):acc) xs (ys ++ [x])

nrPermutations::[(Int, a)]->[[a]]
nrPermutations x | length x == 1 = [take (fst (head x)) (repeat (snd (head x)))]
nrPermutations xs = concat (map helper (circularPermutations xs))
  where helper ((1,x):xs) = map ((:) x)(nrPermutations xs)
        helper ((n,x):xs) = map ((:) x)(nrPermutations ((n - 1, x):xs))
like image 117
gcbenison Avatar answered Sep 20 '22 00:09

gcbenison


Use the following recursive algorithm:

PermutList Permute(SymArray fullSymArray){
    PermutList resultList=empty;
    for( each symbol A in fullSymArray, but repeated ones take only once) {
       PermutList lesserPermutList=  Permute(fullSymArray without A)
       for ( each SymArray item in lesserPermutList){
            resultList.add("A"+item);
       }
    }
    return resultList;
}

As you see, it is very easy

like image 41
Gangnus Avatar answered Sep 24 '22 00:09

Gangnus