给定一个大小为n的列表,编写一个程序以返回每个列表中包含的所有可能的元素组合。
例:
输出:
顺序无关紧要,但是困难的部分是:您不能使用递归。我的解决方案:
void combos(const char *string) { int i, j, k; int len = strlen(string); for (i = 0; i < len - 2; i++) { for (j = i + 1; j < len - 1; j++) { for (k = j + 1; k < len; k++) printf("%c%c%c\n", string[i], string[j], string[k]); } } }
如您所见,只有在我事先知道列表数量的情况下,它才有效。我很好奇递归是否是解决它的唯一方法。
就像将数字递增一样,例如以3为底的数字:
000 001 002 010 011 ... 222
现在,将每个数字视为每个嵌套列表的索引。您将拥有与嵌套列表一样多的数字,即外部列表的大小。
每个数字的“基数”可能不同,并且是相应嵌套列表的大小。如果嵌套列表很大,则“数字”可以是非常大的数字。
因此,您首先创建“数字”或索引值的列表,然后将它们初始化为0。然后,您可以在这些索引处打印元素的值。然后,您增加最后一个索引值,根据需要进行滚动,就像正常数字一样,在第一个索引值滚动时停止。
0
这是使用数组数组(即)的Java实现String[][]。您可以根据需要轻松更改为List<List<String>>或List<String[]>。
String[][]
List<List<String>>
List<String[]>
@SafeVarargs public static void printCombos(String[] ... lists) { if (lists.length == 0) throw new IllegalArgumentException("No lists given"); for (String[] list : lists) if (list.length == 0) throw new IllegalArgumentException("List is empty"); int[] idx = new int[lists.length]; for (;;) { // Print combo for (int i = 0; i < lists.length; i++) { if (i != 0) System.out.print(' '); System.out.print(lists[i][idx[i]]); } System.out.println(); // Advance to next combination for (int i = lists.length - 1; ++idx[i] == lists[i].length; ) { idx[i] = 0; if (--i < 0) return; // We're done } } } public static void main(String[] args) { String[][] data = { { "x", "z" }, { "a", "b", "c" }, { "o", "p" } }; printCombos(data); }
输出值
x a o x a p x b o x b p x c o x c p z a o z a p z b o z b p z c o z c p
如果您使用列表而不是数组,那么代码将使用get(int),这可能并不总是对性能有好处,例如for LinkedList。
get(int)
LinkedList
如果是这种情况,请用替换int[] idx,使用Iterator[]对应列表的迭代器初始化每个数组条目。然后,通过Iterator从相关列表中检索新的数字,将“数字”重置为0 。
int[] idx
Iterator[]
Iterator
在这种情况下,它们甚至不必是列表,而可以是任何种类的集合,或更具体地说是Iterable对象。
Iterable