计算长度为K的可能int序列的列表

时间:2015-09-25 00:12:50

标签: java sequences

假设我可以有一个长度为K的整数序列。这些值中的每一个都可以是从1到N的任何int。如何计算遵循此模式的所有可能序列的列表?我知道这很多,N ^ K,但我打算处理较小的数字。

修改 在Java中,但伪代码很好

2 个答案:

答案 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的第一个解决方案。他以比你特定问题更一般的形式给出它,所以我会根据你的要求调整它。我切换了nk,因此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在适当的范围内。