假设我可以有一个长度为K的整数序列。这些值中的每一个都可以是从1到N的任何int。如何计算遵循此模式的所有可能序列的列表?我知道这很多,N ^ K,但我打算处理较小的数字。
修改 在Java中,但伪代码很好
答案 0 :(得分:0)
更新为1到N,而不是0到N-1
将其视为递增基数为N的K个数字。这使得一个简单的非递归实现:
int[] seq = new int[K];
Arrays.fill(seq, 1);
OUTER: while (true) {
System.out.println(Arrays.toString(seq));
for (int i = K - 1; true; i--) {
int v = seq[i] + 1;
if (v <= N) {
seq[i] = v;
break;
}
if (i == 0)
break OUTER;
seq[i] = 1;
}
}
E.g。对于K = 2和N = 3:
[1, 1]
[1, 2]
[1, 3]
[2, 1]
[2, 2]
[2, 3]
[3, 1]
[3, 2]
[3, 3]
答案 1 :(得分:0)
这是计算机科学某些领域的常见问题。对于解决这些类型问题的一个很好的参考是Donald Knuth的计算机编程艺术。他解决了本书第7.2.1.1节中生成所有n元组的特殊问题。可以找到包含此部分的本书部分的草稿(PDF格式)here。
本书中讨论了几种解决方案,哪种解决方案最好可能取决于您的具体情况。我在这里给出的答案对应于Knuth的第一个解决方案。他以比你特定问题更一般的形式给出它,所以我会根据你的要求调整它。我切换了n
和k
,因此n
是序列的长度,k
是您要使用的最大整数,而不是存储所有n元组,我使用访问者模式访问每个n元组。如果要存储所有访问的n元组,可以实现访问者存储每个访问过的n元组的副本。
我没有对此进行过测试,但即使存在一些错误,我也会想到这个想法。
public interface Visitor {
void visit(int[] nTuple);
}
public void generateAndVisitNTuples(int n, int k, Visitor v) {
int[] nTuple = new int[n];
// initialize each digit to one
for (int i = 0; i < n; ++i) {
nTuple[i] = 1;
}
while (true) {
v.visit(nTuple);
int j = n - 1;
while (j >= 0 && nTuple[j] == k) {
// this is a digit j that is at the maximum, so reset it to 1
nTuple[j] = 1
--j;
}
if (j < 0) {
// all digits j were at maximum, so all n-tuples have been visited
break;
}
// this digit j is not yet at its maximum, so increase it
++nTuple[j];
}
}
您可能希望实现一些边界以确保传入方法的n和k在适当的范围内。