Algorithm 确定符号是否为第i个组合nCr的一部分
更新: 我最终需要的是组合数学和解列。 下面的链接很有帮助: 问题Algorithm 确定符号是否为第i个组合nCr的一部分,algorithm,function,combinations,combinatorics,Algorithm,Function,Combinations,Combinatorics,更新: 我最终需要的是组合数学和解列。 下面的链接很有帮助: 问题 给定N个符号的列表,如{0,1,2,3,4…} 以及这些的NCr组合 例如,NC3将产生: 0 1 2 0 1 3 0 1 4 ... ... 1 2 3 1 2 4 etc... 对于第i个组合(i=[1..NCr]),我想确定一个符号是否是它的一部分。 Func(N,r,i,s)=真/假或0/1 从上面继续 第一个组合包含0 1 2,但不包含3 F(N,3,1,"0") = TRUE
给定N个符号的列表,如{0,1,2,3,4…}
以及这些的NCr组合 例如,NC3将产生:
0 1 2
0 1 3
0 1 4
...
...
1 2 3
1 2 4
etc...
对于第i个组合(i=[1..NCr]),我想确定一个符号是否是它的一部分。Func(N,r,i,s)=真/假或0/1
从上面继续 第一个组合包含0 1 2,但不包含3
F(N,3,1,"0") = TRUE
F(N,3,1,"1") = TRUE
F(N,3,1,"2") = TRUE
F(N,3,1,"3") = FALSE
当前可能有用或相关的方法和技巧。与矩阵的关系 对于r=2,例如4C2,组合是2D矩阵的上半部分(或下半部分)
1,2 1,3 1,4
----2,3 2,4
--------3,4
对于r=3,它是3D矩阵或立方体的角
对于r=4,它是4D矩阵的“角”,依此类推
另一种关系理想情况下,解决方案的形式类似于以下问题的答案: 长度为r的组合列表中的第n个组合(允许重复),可以计算第i个符号
使用整数除法和余数: n/r^i%r=(0表示第0个符号,1表示第1个符号…等) 例如,对于3个符号中的第6个梳,第0个第一和第二个符号为:
i = 0 => 6 / 3^0 % 3 = 0
i = 1 => 6 / 3^1 % 3 = 2
i = 2 => 6 / 3^2 % 3 = 0
第六个梳子将是0 2 0
我需要类似的东西,但不允许重复
感谢您关注这个问题:凯文。我相信你的问题在于或子集的问题 我将从软件包中用Mathematica为您提供一个实现,但是上面的Google链接可能是一个更好的起点,除非您熟悉语义
UnrankKSubset::usage = "UnrankKSubset[m, k, l] gives the mth k-subset of set l, listed in lexicographic order."
UnrankKSubset[m_Integer, 1, s_List] := {s[[m + 1]]}
UnrankKSubset[0, k_Integer, s_List] := Take[s, k]
UnrankKSubset[m_Integer, k_Integer, s_List] :=
Block[{i = 1, n = Length[s], x1, u, $RecursionLimit = Infinity},
u = Binomial[n, k];
While[Binomial[i, k] < u - m, i++];
x1 = n - (i - 1);
Prepend[UnrankKSubset[m - u + Binomial[i, k], k-1, Drop[s, x1]], s[[x1]]]
]
{0, 3, 4}
产生集合{0,1,2,3,4}的第6个(从0开始索引)长度-3组合。这个问题有一个非常有效的算法,它也包含在最近出版的:
Knuth,《计算机编程艺术》,第4A卷(第7.2.1.3节) 因为您不关心组合的生成顺序,所以让我们使用组合的字典顺序,其中每个组合按降序列出。因此,对于r=3,3个符号的前11个组合将是:210、310、320、321、410、420、421、430、431、432、510。这种排序的优点是枚举独立于n;事实上,它是对{0,1,2,…}中3个符号的所有组合的枚举 有一种标准方法可以直接生成给定i的第i个组合,因此要测试符号
s
是否是第i个组合的一部分,只需生成它并进行检查即可
方法
有多少个r符号的组合以特定符号s开始?剩余的r-1位置必须来自s符号0,1,2,…,s-1,所以它是(s选择r-1),其中(s选择r-1)或C(s,r-1)是二项式系数,表示从s对象中选择r-1对象的方法的数量。因为这对所有s都是正确的,第i个组合的第一个符号是最小的s,因此
&总和;k=0s(k选择r-1)≥ 一,
一旦知道了第一个符号,问题就归结为找到第(i-&Sum;k=0s-1(k选择r-1))个r-1符号组合,其中我们减去了以小于s的符号开始的组合
代码
Python代码(您可以更高效地编写C(n,r)
,但这对我们来说已经足够快了):
#/usr/bin/env python
tC={}
def C(n,r):
如果tC.具有_键((n,r)):返回tC[(n,r)]
如果r>n-r:r=n-r
如果r我已经编写了一个类来处理处理二项式系数的常用函数,这是您的问题所属的问题类型。它执行以下任务:
将任意N选择K的所有K索引以良好格式输出到文件。可以用更具描述性的字符串或字母替换K索引。这种方法使得解决这类问题变得非常简单
将K索引转换为已排序二项系数表中某个条目的正确索引。这种技术比以前发布的依赖于迭代的技术要快得多。它通过使用帕斯卡三角形固有的数学特性来实现这一点。我的论文谈到了这一点。我相信我是第一个发现并发表这项技术的人,但我可能错了
将已排序的二项式系数表中的索引转换为相应的K索引
使用此方法计算二项式系数,它不太可能溢出,并且适用于较大的数字
该类是用.NETC#编写的,它提供了一种通过使用泛型列表来管理与问题相关的对象(如果有)的方法。这个类的构造函数接受一个名为InitTable的bool值,如果为true,它将创建一个通用列表来保存要管理的对象。如果此值为false,则不会创建表。执行上述4种方法不需要创建表。提供了访问器方法来访问表
有一个关联的测试类,它显示了如何使用该类及其方法。它已经过2个案例的广泛测试,没有已知的bug
要阅读有关此类的信息并下载代码,请参阅
这门课可以很容易地应用于你的问题。如果您拥有二项式系数表的秩(或索引),那么只需调用在数组中返回K索引的类方法。然后,遍历返回的数组,查看是否有任何K索引值与您拥有的值匹配。非常简单…也许可以添加作业
tag@Amit为什么你认为这是家庭作业?问题交叉张贴在。(所以我在这里交叉发布了我的答案。:p有更多的代码,没有TeX标记。)更新:组合和取消分级最终是我需要的。下面的链接帮助很大:谢谢你的接受。我很高兴这有帮助。
UnrankKSubset[5, 3, {0, 1, 2, 3, 4}]
{0, 3, 4}