让我们考虑一个函数P(n)
,该函数将自然数作为输入并返回这样的输出:
P(1) = [[0], [1]]
P(2) = [[0, 0], [1, 0], [0, 1], [1, 1]]
P(3) = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]]
P(4) = [[0, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0], [1, 1, 0, 0], [0, 0, 1, 0], [1, 0, 1, 0], [0, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1], [1, 1, 0, 1], [0, 0, 1, 1], [1, 0, 1, 1], [0, 1, 1, 1], [1, 1, 1, 1]]
我不知道如何正式称呼它(组合?),但是我认为这个例子足以理解我的想法。
我使用Java来实现:
static byte[][] permutate(int n) {
byte[][] ps = new byte[1 << n][n];
go(ps, 0, ps.length / 2, ps.length, n - 1);
return ps;
}
static void go(byte[][] as, int l, int m, int h, int depth) {
if (depth < 0)
return;
for (int i = l, j = m; i < m && j < h; ++i, ++j) {
as[i][depth] = 0;
as[j][depth] = 1;
}
go(as, l, (l + m) / 2, m, depth - 1);
go(as, m, (m + h) / 2, h, depth - 1);
}
此实现返回正确的结果,但是其内存使用量呈指数增长(指数),特别是在O(2^n)
中!
这就是我想要的:此功能,但是很懒!仅在需要它们时生成这些元组(它们实际上是数组,但这不是重点)。所以,我的问题:
此函数是否可能返回迭代器而不是数组?如果可以,怎么办?
答案 0 :(得分:0)
您可以使用不使用递归的其他方法:
public static void main(String[] args) throws Exception {
Iterator<byte[]> iterator = new PermutationIterator(4);
while (iterator.hasNext()) {
System.out.println(Arrays.toString(iterator.next()));
}
}
private static final class PermutationIterator implements Iterator<byte[]> {
private final int max;
private final int n;
private int current;
public PermutationIterator(int n) {
this.n = n;
this.max = (int) Math.pow(2, n);
}
@Override
public boolean hasNext() {
return current < max;
}
@Override
public byte[] next() {
byte[] bytes = new byte[n];
for (int i = 0; i < n; i++) {
bytes[i] = (byte) ((current >>> i) & 1);
}
current++;
return bytes;
}
但是,请注意,这只会为n <= 31
产生正确的结果。如果要支持更大的n
,则应使用long
甚至是BigInteger
。
输出:
[0, 0, 0, 0]
[1, 0, 0, 0]
[0, 1, 0, 0]
[1, 1, 0, 0]
[0, 0, 1, 0]
[1, 0, 1, 0]
[0, 1, 1, 0]
[1, 1, 1, 0]
[0, 0, 0, 1]
[1, 0, 0, 1]
[0, 1, 0, 1]
[1, 1, 0, 1]
[0, 0, 1, 1]
[1, 0, 1, 1]
[0, 1, 1, 1]
[1, 1, 1, 1]