扭曲的二项式系数

Binomial coefficient with a twist

本文关键字:二项式      更新时间:2023-10-16

现在,要枚举集合

中所有k=4个组合
Set = [1; 2; 3; 4; 5; 6; 7; 8]

我使用预构建的Matlab函数nchoosek来计算二项式系数。n个事物一次发生k次的组合次数是由n!/((n - k)!k !)。

现在,假设我有一个包含n = 8个元素的数据集:

Set = [1.A; 2.B; 3.C; 4.D; 5.B; 6.D; 7.C; 8.A]

我想枚举"Set"中4个整数的所有组合,但有一个转折:在任何组合中,我必须只有一个元素具有相同的字母(顺序无关紧要)。例如:

[1.;2. b;6. d;7.C]是一个有效的组合,但不是[1.A;2. b;6. d;8.]。

有[1.;2. b;6. d;7.C],我仍然必须生成这个组合[8.A;2. b;6. d;7. c]

由于A、B、C和D出现了2次,所以不必生成70种组合,而只需生成2*2*2*2 = 16种组合。70-16 = 54的其他组合与我的问题无关,我宁愿不生成它们,因为它在计算上变得越来越庞大。目前,我生成了70个组合,然后使用一些逻辑来删除所有不相关的组合。

我的问题是:

  1. 这种类型的组合有一个名称吗?(可以帮助我查找信息,更好地了解问题)
  2. 是否有一些现有的算法允许计算?用Matlab或c++编写。请,如果它是充满regex,一点解释将是受欢迎的…

将设置转换为窗体

[A[1, 8], B[2,5], C[3,7], D[4,6]]

通过字母键生成基组合-这里只有一个(C(4,4))基组合(A,B,C,D)并使用数字子键扩展组合(例如,递归方法)

一般递归算法:

combs(index,multiset,k,result):
  if length of result == k:
    output result
    return
  if length of result + length of multiset - index < k:
    return
  for j in multiset[index]:
    combs(index + 1,multiset,k,result with multiset[index][j] added)
  combs(index + 1,multiset,k,result)

JavaScript的例子:

function combs(i,multiset,k,result){
  if (result.length == k){
    console.log(result);
    return;
  }
  if (result.length + multiset.length - i < k)
    return;
  for (var j=0; j<multiset[i].length; j++){
    _result = result.slice();
    _result.push(multiset[i][j]);
    combs(i + 1,multiset,k,_result);
  }
  combs(i + 1,multiset,k,result);
}
combs(0,[["1.A","8.A"],["2.B","5.B"],["3.C","7.C"],["4.D","6.D"]],4,[]);

你的扭转给问题增加了约束。据我所知,这个新问题没有专门的名称,它和其他问题一样,只是一个组合问题。

注意,您最终所做的是为结果集中的每个可能的"槽"添加选项。常规选择公式的基本假设是,给定的项可以在集合中,也可以不在集合中。注意,对于A、B、C和D组,要么

  1. 该类型的单个整数在结果集中,

  • 该类型的整数根本不在集合中
  • 因此,选择结果集中的整数类型与选择原问题结果集中的实际整数是类似的!一旦选择了结果集中的整数类型,就可以任意选择将每种类型的整数放入结果集中。

    在你的例子中,如果我们必须选择4种类型放入集合中,那么这样做的方法的数量是4选择4 = 1 (A,B,C,D)。A型有2个选项,B型有2个选项,C型有2个选项,D型有2个选项,所以有2*2*2*2=16套可供选择

    这只是具有唯一性检查的标准C(N, K)。下面的代码是JavaScript,但将其转换为c++应该不会太难。

    function nchoosekUnique(arr, k, combo, result) {
      if(combo.length === k) {
        result.push(combo);
        return result;
      }
      for(var i=0; i < arr.length - k; i++) {
        // UNIQUE CHECK
        var unique = true;
        for(var u=0; u<combo.length; u++) {
          if(combo[u][1] == arr[i][1]) { 
            unique = false; 
            continue; 
          }
        }
        //
        if(unique === true) {
          var comboCpy = combo.slice(0);
          var arrCpy = arr.slice(0);
          comboCpy[comboCpy.length] = arrCpy.splice(i, 1)[0];
          nchoosekUnique(arrCpy, k, comboCpy, result);
        }
      }
      return result;
    }
    var arr = [[1,"A"], [2,"B"], [3,"C"], [4,"D"], [5,"B"], [6,"D"], [7,"C"], [8,"A"]];
    JSON.stringify(nchoosekUnique(arr, 4, [], []), null, 't');
    

    注意如果你的K非常大,你可能想要使用Set (HashSet)实现的组合变量,而不仅仅是一个数组。