Algorithm to list unique permutations of string with duplicate letters

后端 未结 3 1353
星月不相逢
星月不相逢 2020-11-30 11:48

For example, string \"AAABBB\" will have permutations: \"ABAABB\", \"BBAABA\", \"ABABAB\", etc

What\'s a good algorithm for generating the permutations? (And what\

3条回答
  •  抹茶落季
    2020-11-30 12:29

    Since you actually want to generate the permutations instead of just counting them, the best complexity you can hope for is O(size_of_output).

    Here's a good solution in java that meets that bound and runs very quickly, while consuming negligible space. It first sorts the letters to find the lexographically smallest permutation, and then generates all permutations in lexographic order.

    It's known as the Pandita algorithm: https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order

    import java.util.Arrays;
    import java.util.function.Consumer;
    
    
    public class UniquePermutations
    {
        static void generateUniquePermutations(String s, Consumer consumer)
        {
            char[] array = s.toCharArray();
            Arrays.sort(array);
            for (;;)
            {
                consumer.accept(String.valueOf(array));
    
                int changePos=array.length-2;
                while (changePos>=0 && array[changePos]>=array[changePos+1])
                    --changePos;
    
                if (changePos<0)
                    break; //all done
    
                int swapPos=changePos+1;
                while(swapPos+1 < array.length && array[swapPos+1]>array[changePos])
                    ++swapPos;
    
                char t = array[changePos];
                array[changePos] = array[swapPos];
                array[swapPos] = t;
    
                for (int i=changePos+1, j = array.length-1; i < j; ++i,--j)
                {
                    t = array[i];
                    array[i] = array[j];
                    array[j] = t;
                }
            }
        }
    
        public static void main (String[] args) throws java.lang.Exception
        {
            StringBuilder line = new StringBuilder();
            generateUniquePermutations("banana", s->{
                if (line.length() > 0)
                {
                    if (line.length() + s.length() >= 75)
                    {
                        System.out.println(line.toString());
                        line.setLength(0);
                    }
                    else
                        line.append(" ");
                }
                line.append(s);
            });
            System.out.println(line);
        }
    }
    

    Here is the output:

    aaabnn aaanbn aaannb aabann aabnan aabnna aanabn aananb aanban aanbna
    aannab aannba abaann abanan abanna abnaan abnana abnnaa anaabn anaanb
    anaban anabna ananab ananba anbaan anbana anbnaa annaab annaba annbaa
    baaann baanan baanna banaan banana bannaa bnaaan bnaana bnanaa bnnaaa
    naaabn naaanb naaban naabna naanab naanba nabaan nabana nabnaa nanaab
    nanaba nanbaa nbaaan nbaana nbanaa nbnaaa nnaaab nnaaba nnabaa nnbaaa
    

提交回复
热议问题