使用递归来使用迭代器查找字符串的排列

时间:2015-02-12 21:12:34

标签: java recursion iterator permutation

正如标题所暗示的那样,我在尝试以递归方式确定给定String的所有排列时遇到了困难。问题是String必须通过对象的构造函数给出,然后逐个找到每个排列。基本上,它必须像这样工作:

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

以下是我使用的代码,但似乎无法正常使用,我也不知道如何修复它。

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;
    }
}

现在节目打印&#34;吃&#34;和&#34; eta&#34;但之后它通过第二个堆栈的StringIndexOutOfBounds错误。任何帮助解决这个问题都非常感谢。

3 个答案:

答案 0 :(得分:2)

不是仅提供修复程序,而是让我帮助诊断您的问题,然后您就可以开始修复它。

如果仔细查看代码,您会发现hasMorePermutationspos == word.length() - 1条件已经过去了nextPermutation。这意味着当pos指向字符串中的最后一个字符时,将运行pos。但是在第三个分支执行的情况下,您递增word.substring(pos + 1)然后调用pos + 1。此时{{1}}将大于将抛出异常的字符串的长度。

我希望修复程序相当容易。

答案 1 :(得分:0)

尝试此代码 - 为任何给定字符串生成排列

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(i.e 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));

		}
	}

}

答案 2 :(得分:0)

在你的hasMorePermutation方法中做一点改动,如下所示,解决StringIndexOutOfBounds异常。

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