简体   繁体   中英

Use recursion to find permutations of string using an iterator

As the title implies, I'm having difficulty trying to recursively determine all the permutations of a given String . The catch is that String has to be given through a constructor of an object and then each of the permutations be found one by one. Basically, it has to work like this:

PermutationIterator iter = new PermutationIterator("eat");
while (iter.hasMorePermutations())
   System.out.println(iter.nextPermutation());

Here is the code that I'm using but doesn't seem to work and I don't know how to fix it.

public class PermutationIterator {

    private String word;
    private int pos;
    private PermutationIterator tailIterator;
    private String currentLetter;

    public PermutationIterator(String string) {
        word = string;
        pos = 0;
        currentLetter = string.charAt(pos) + "";
        if (string.length() > 1)
            tailIterator = new PermutationIterator(string.substring(pos + 1));
    }

    public String nextPermutation() {
        if (word.length() == 1) {
            pos++;
            return word;
        } else if (tailIterator.hasMorePermutations()) {
            return currentLetter + tailIterator.nextPermutation();
        } else {
            pos++;
            currentLetter = word.charAt(pos) + "";
            String tailString = word.substring(0, pos) + word.substring(pos + 1);
            tailIterator = new PermutationIterator(tailString);
            return currentLetter + tailIterator.nextPermutation();
        }

    }

    public boolean hasMorePermutations() {
        return pos <= word.length() - 1;
    }
}

Right now the program prints "eat" and "eta" but after that it through a StringIndexOutOfBounds error off of the second stack. Any help with solving this is much appreciated.

Rather than just supplying the fix let me help diagnose your issue and then you can have a go at fixing it.

If you look carefully at your code you'll see that the hasMorePermutations condition passes when pos == word.length() - 1 . That means nextPermutation will be run when pos is pointing to the last character in the string. But in that case when the third branch executes you increment pos and then call word.substring(pos + 1) . At that point pos + 1 will be larger than length of the string which will throw the exception.

I expect the fix will be fairly easy.

try this code - generates permutations for any given string

 package testing; import java.util.ArrayList; import java.util.List; public class Permutations { /* * You will get n! (factorial) - permutations from this * * Just like this Example: abc (3! = 6 permutations) [abc acb bac bca cab * cbc] */ static String str = "abcd"; static char[] ch = str.toCharArray(); static List<String> s1 = new ArrayList<>(); static List<String> s2 = new ArrayList<>(); public static void main(String[] args) { // s1 - list stores initial character from the string s1.add(String.valueOf(ch[0])); // recursive loop - char by char for (int k = 1; k < ch.length; k++) { // adds char at index 0 for all elements of previous iteration appendBefore(s1, ch[k]); // adds char at last index for all elements of previous iteration appendAfter(s1, ch[k]); // adds char middle positins like a^b^C - if prev list stores // elements // whose size() is 3 - then it would have 2 positions fill /* * say d is next char - d should be filled in _^_^_ _ positions are * previous permuions for 3 chars a,b,c(ie 6 permutations */ appendMiddle(s1, ch[k], k); // for every iteration first clear s1 - to copy s2, which contains // previous permutatons s1.clear(); // now copy s2 to s1- then clear s2 // - this way finally s2 contains all the permutations for (int x = 0; x < s2.size(); x++) { s1.add(s2.get(x)); } System.out.println(s1); System.out.println(s1.size()); s2.clear(); } } private static void appendMiddle(List str, char ch, int positions) { for (int pos = 1; pos <= positions - 1; pos++) { for (int i = 0; i < str.size(); i++) { s2.add(str.get(i).toString().substring(0, pos) + String.valueOf(ch) + str.get(i).toString().substring(pos, str.get(i).toString().length())); } } } private static void appendBefore(List str, char ch) { for (int i = 0; i < str.size(); i++) { s2.add(String.valueOf(ch) + str.get(i)); } } private static void appendAfter(List str, char ch) { for (int i = 0; i < str.size(); i++) { s2.add(str.get(i) + String.valueOf(ch)); } } } 

do a little change in your hasMorePermutation method as below to solved StringIndexOutOfBounds exception.

public boolean hasMorePermutations()
{
    return pos < word.length() - 1;
}

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