可变数量的嵌套循环

我在java中做了一个单词解码器。 现在我有一个程序,可以打印从3个或更多字母(没有重复)的单词中选择的3个字母的所有重新排列。 因此,例如,如果参数是abcd ,它将打印此:

[[abc,abd,acb,acd,adb,adc,bac,bad,bca,bcd,bda,bdc,cab,cad,cba,cbd,cda,cdb,dab,dac,dba,dbc,dca,dcb] ]

我正在使用排列填充2D数组列表。 现在,2D数组中只有一个数组,其中包含3个字母的排列。 我希望2D数组有1个字母,2个字母,3个字母等的permations数组,停止在单词的长度。 问题是我需要一个可变数量的嵌套for循环来完成这个。 对于3个字母的排列,我有3个嵌套for循环。 每个循环遍历参数中的字母。

public static void printAllPermuations(String word) { int len = word.length(); ArrayList lets = new ArrayList(); //this array of letters allows for easier access //so I don't have to keep substringing for (int i = 0; i < len; i++) { lets.add(word.substring(i, i + 1)); } ArrayList<ArrayList> newWords = new ArrayList<ArrayList>(); newWords.add(new ArrayList()); for (int i = 0; i < len; i++) { for (int j = 0; j < len; j++) { for (int k = 0; k < len; k++) { if (i != j && i != k && j != k) //prevents repeats by making sure all indices are different { newWords.get(0).add(lets.get(i) + lets.get(j) + lets.get(k)); } } } } System.out.println(newWords); } 

我看过其他post,我听说递归可以解决这个问题。 但我不知道如何实现这一点。 而且我也看到了一些我不理解的复杂解决方案。 我要求最简单的解决方案,无论是否涉及递归。

使用递归方法,您可以将一个循环放在函数中,将循环参数传递给该函数。 然后从函数的循环中,它调用它来嵌套另一个循环。

 void loopFunction(ArrayList> newWords, int level) { if (level == 0) { // terminating condition if (/* compare the indices by for example passing down a list with them in */) { newWords.get(...).add(...); } } else {// inductive condition for (int i = 0; i < len; i++) { loopFunction(newWords, level-1); } } } 

因此,对于您的示例,您需要3级递归,因此您可以使用以下命令开始递归:

 loopFunction(newWords, 3); 

编辑

由于你遇到麻烦,这是一个工作版本。 它保留了要比较的索引列表,并随着它的建立而构建字符串。 重新排列的单词将添加到每个级别的2D数组中,以获得所有长度的单词。 使用递归最简单的方法是在function上进行思考而不是更改并保持变量不可变(不可更改)。 这段代码主要是这样做的,虽然我更新了indices而不是为了方便而创建一个新副本。

 void loopFunction(ArrayList lets, ArrayList> newWords, int level, ArrayList indices, String word) { if (level == 0) { // terminating condition return; } else { // inductive condition for (int i = 0; i < lets.size(); i++) { if (!indices.contains(i)) { // Make sure no index is equal int nextLevel = level-1; String nextWord = word+lets.get(i); newWords.get(level-1).add(nextWord); indices.add(i); loopFunction(lets, newWords, nextLevel, indices, nextWord); indices.remove((Integer) i); } } } } 

我不会给你实际的代码,但是这应该让你知道递归的样子(我相信还有其他的递归方式:P)

 void findAllCombination(String tmpResult, String rawString, int noOfChar, List allCombinations) { if (tmpResult.size() == noOfChar) { allCombinations.add(tmpResult ); } else { for (i in 0 to rawString.size()) { findAllCombination(tmpResult + rawString[i], rawString.removeCharAt(i), noOfChar, allCombinations); } } } List foo(String input, int level) { List allResults = ...; findAllCombination("", input, level, allResults); return allResults; } 

主要的递归部分是findAllCombination 。 这个想法是严格的前进。 对于找到所有排列的方法是,对于我们拥有的rawString输入,我们逐个取出字符,并附加到先前找到的tmpResult,并使用该tmpResult进行进一步处理。 一旦我们达到了tmpResult足够长的点,那么我们将tmpResult放到结果allCombinations列表中。

(foo()方法只是为了让你的调用更容易:实际完成工作的P代码只有6行,不包括只有括号的行而忽略了为了更好的可读性而故意破坏的行)

基于@DrYap所说的,我写了这个(它与他有点不同):

这是启动它的代码:

 for(int i = 1; i <= len; i++) { newWords.add(new ArrayList()); loop(i); } 

这是循环方法。 许多变量被声明为实例变量,所以我不必将它们传递给参数:

 public static void loop(int level) { if (level == 0) { int pos = indices.size() - 1; int pos2 = newWords.get(pos).size(); newWords.get(pos).add(""); for (Integer letIndex : indices) { String previous = newWords.get(pos).get(pos2); newWords.get(pos).set(pos2, previous + lets.get(letIndex)); } } else { for (int i = 0; i < len; i++) { if (!indices.contains(i)) { int indicesIndex = indices.size(); indices.add((Integer) i); loop(level - 1); indices.remove(indicesIndex); } } } }