给定整数集,{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)更好的时间内完成此操作。任何确认/指导将不胜感激。
答案 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)。