检索特定组合

时间:2014-07-17 10:07:09

标签: java algorithm combinations

给定整数集,{x | 1< = x< = n}。考虑一个组合,比如50C6(从50中选择6)。计算组合的数量并迭代它们(按排序顺序)很容易。

例如,这可以解决问题:

public static void combo(int[] combo, int index, int f, int t) {
    if (index >= combo.length) {
        // display combination
        // ...
        return;
    }
    for (int i = f; i <= t - (combo.length - index) + 1; i++) {
        combo[index] = i;
        combo(combo, index + 1, i + 1, t);
    }
}

对于上面的内容,调用combo(new int [] {0,0,0,0},0,1,9)将按排序顺序列出所有9C4组合,全部126个。

我想要的是以下内容。给定k,我希望算法给出组合。

// Select r from c and return combination k.
public static int[] combo(int c, int r, int k) {
}

例如,组合(3,2,1)应该返回{1,2}并且组合(3,2,3)应该返回{2,3}(假设第一个组合是1而不是0 - 但是& #39; s琐碎的)。

在O(nCr)中执行此操作非常简单且占用内存很少...在O(1)中执行此操作也很容易,但需要大量内存才能实现更大的组合,并且需要预先计算。我不知道在不使用查找表的情况下,是否可以在比O(nCr)更好的时间内完成此操作。任何确认/指导将不胜感激。

2 个答案:

答案 0 :(得分:1)

所以你可以用公式n!/(p!*(n-p)!)找到nCp的值。所以说你正在解决4C3并且你正在寻找第k组合。如果第一个值是1那么这意味着你剩下3C2计算为3.所以如果k <1。 3第一个值是1.如果不是,则转到3C2 + 3C1获取第二个值。你回避了这条线。不确定它是否真的更快(计算nCp),但这是一个有趣的方式来思考这个问题。

答案 1 :(得分:0)

好的,我已经解决了,我对最终结果非常满意。基本思路如下:

我们想说我们想要nCr的第k个条目。然后,我们从1开始的组合数是(n-1)C(r-1),2是(n-2)C(r-2)等。所以,你所要做的就是找出第一个点需要去哪个数字,然后为每一个r点重复这个过程。

例如,让我们说我们想要9C3的第30个条目。对于1,我们有8C2 = 28.这还不够。对于2,7C2 = 21.因此,第一个数字必须是2,以2开头的第一个数字是条目29.所以现在你只需要为第二个和第三个条目重复这个过程。

非递归解决方案如下:

public static int[] getCombo(int n, int r, int k) {
    int[] result = new int[r];
    int cur = 1;
    int sum =0;
    while (r > 0) {
        int tot = c(n - cur, r - 1);
        if (sum + tot < k) {
            sum += tot;
            cur++;
        } else {
            result[result.length - r] = cur++;
            r--;
        }
    }
    return result;
}

上面的函数c(),只需计算&#34; n选择r&#34;。 我特别喜欢这个,因为它是O(r)。