【问题标题】:Use recursion to find permutations of string using an iterator使用迭代器使用递归查找字符串的排列
【发布时间】:2015-02-12 21:12:34
【问题描述】:

正如标题所暗示的,我很难尝试递归地确定给定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;
    }
}

现在程序打印“eat”和“eta”,但之后它通过第二个堆栈的StringIndexOutOfBounds 错误。非常感谢任何解决此问题的帮助。

【问题讨论】:

  • 你忘了说你的代码抛出了StringIndexOutOfBoundException....对吗?

标签: java recursion iterator permutation


【解决方案1】:

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

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

我希望修复会相当容易。

【讨论】:

  • 如果我在pos == word.length() - 1 和下面的所有内容时停止.substring() 调用,我会返回什么?我将它用hasMorePermutations() 的 if 语句包围,但我无法弄清楚返回,因为返回原始语句会导致堆栈溢出。
  • 老实说,我认为您使用堆叠迭代器模拟递归的技术过于复杂。除非您期望使用非常长的字符串,否则我建议您在构造函数中创建所有排列的列表,然后在您的方法中遍历它们。更简单、更明显。
  • 如果我不能很快提出解决方案,我可能会这样做。无论如何,这是为了上课,所以我没有决定这样做。
  • @Kyefer 这里有一个关于修复的提示:当你已经在字符串的末尾时,你不需要将任何超过pos 的东西附加到tailString - 那里没有任何东西可以附加!如果这没有意义,请告诉我,我会给你更直接的帮助。
【解决方案2】:

试试这个代码 - 为任何给定的字符串生成排列

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

		}
	}

}

【讨论】:

    【解决方案3】:

    在你的 hasMorePermutation 方法中做一点改变来解决 StringIndexOutOfBounds 异常。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-06
      • 2014-05-16
      • 2015-03-07
      • 1970-01-01
      • 2014-12-23
      • 1970-01-01
      相关资源
      最近更新 更多