如果您正在寻找一种获取唯一组合的词典索引或排名而非排列的方法,那么您的问题属于二项式系数。二项式系数处理在N个项目中选择K个唯一组合的问题。
我已经用C#编写了一个类来处理与二项式系数相关的常见函数。它执行以下任务:
将任何N选K的所有K指数以漂亮的格式输出到文件中。可以用更具描述性的字符串或字母替换K指数。
将K指数转换为排序二项式系数表中条目的正确词典序索引或排名。这种技术比依赖迭代的旧技术快得多。它通过使用帕斯卡三角形固有的数学特性来实现,与迭代集合相比非常高效。
将排序二项式系数表中的索引转换为相应的K指数。我认为这也比旧的迭代解决方案更快。
使用
Mark Dominus方法计算二项式系数,这样不太可能溢出,并且适用于更大的数字。
该类是用.NET C#编写的,并提供了一种使用通用列表来管理与问题相关的对象(如果有)的方法。该类的构造函数接受一个名为InitTable的布尔值,当为true时,将创建一个通用列表来保存要管理的对象。如果此值为false,则不会创建该表。不需要创建表格即可使用上述4种方法。提供访问器方法以访问表格。
有一个相关的测试类,显示如何使用该类及其方法。它已经经过了2个案例的广泛测试,没有已知的错误。
阅读有关此类的信息并下载代码,请参见
将二项式系数制表。
以下经过测试的代码将迭代每个唯一的组合:
public void Test10Choose5()
{
String S;
int Loop;
int N = 500;
int K = 3;
BinCoeff<int> BC = new BinCoeff<int>(N, K, false);
int NumCombos = BinCoeff<int>.GetBinCoeff(N, K);
int[] KIndexes = new int[K];
StringBuilder SB = new StringBuilder();
for (int Combo = 0; Combo < NumCombos; Combo++)
{
BC.GetKIndexes(Combo, KIndexes);
int Val = BC.GetIndex(true, KIndexes);
if (Val != Combo)
{
S = "Val of " + Val.ToString() + " != Combo Value of " + Combo.ToString();
Console.WriteLine(S);
}
SB.Remove(0, SB.Length);
for (Loop = 0; Loop < K; Loop++)
{
SB.Append(KIndexes[Loop].ToString());
if (Loop < K - 1)
SB.Append(" ");
}
S = "KIndexes = " + SB.ToString();
Console.WriteLine(S);
}
}
你应该能够很容易地将这个类移植到C++。你可能不需要移植类的通用部分来实现你的目标。你的测试案例中,500选3产生了20,708,500个唯一的组合,可以放在一个4字节的整数中。如果500选3只是一个示例案例,而你需要选择大于3的组合,则必须使用long或者固定点整数。