Algorithm 在列表中查找重复项的最少检查
给定一个序列(d1,d2,…,dn),我想计算所有I!=j其中,如果di=dj,则Dij=1,否则为0 我的代码只有在我Algorithm 在列表中查找重复项的最少检查,algorithm,math,repeat,Algorithm,Math,Repeat,给定一个序列(d1,d2,…,dn),我想计算所有I!=j其中,如果di=dj,则Dij=1,否则为0 我的代码只有在我 prod = 1; for (int i=1; i<n; ++i) { for (int j=i; j<=n; ++j) { prod *= (1 - Dij); } } 但我能做的还有很多。这个表达式实际上总是等于 1 - D12 - D13 - D23 + 3 * D12*D13 - D12*D13*D23 我的问题是: 为
prod = 1;
for (int i=1; i<n; ++i) {
for (int j=i; j<=n; ++j) {
prod *= (1 - Dij);
}
}
但我能做的还有很多。这个表达式实际上总是等于
1 - D12 - D13 - D23 + 3 * D12*D13 - D12*D13*D23
我的问题是:
我可以为你回答1。考虑这两种情况: 案例1:
D13=D23
在这里,您可以将两边的D12
相乘,得到D12*D13=D12*D23
案例2:D13!=D23
这意味着要么d1=d3
XORd2=d3
,要么而不是两者都。因此我们知道,d1!=d2
。这意味着D12=0
。所以
D12 * D13 = 0 * D13 = 0 = 0 * D23 = D12 * D23
当您认为这意味着D13=D23
时,逻辑的问题在于不能除以0
,而D12
可能是0
(第二种情况下通常会发生这种情况)
你的第二个问题很有趣,我一时想不出答案,但这里有一些可能有用的观察结果 将数字
1,2,…,n
绘制成一行:
1 2 3 ... n
给定一个表达式D_1;(i1,j1)*D_1;(i2,j2)*……*D_1;(ik,jk)
,从i1到j1
和i2到j2
形成一条弧,依此类推。这会将该行转换为图形(顶点是数字,边是这些圆弧)
该图的每个连通分量表示数字1,2,…,n
的子集,作为一个整体,这给我们提供了{1,2,…,n}
的一个集合
事实:具有相同对应集合分区的任何两个项都是相等的
例如:
D12 * D23 = D12 * D13
---------
| |
1 -- 2 -- 3 = 1 -- 2 3
有时,这一事实意味着程度与上述情况相同,有时程度会降低,如中所示
D12 * D13 * D23
---------
| |
1 -- 2 -- 3
结果是,现在可以将乘积(1-Dij)表示为集合分区上的和:
\prod_{i<j} ( 1 - Dij ) = \sum_{P set partition of \{1,2,...,n\}} c_P * m_P
当p=P1接头P2接头。。。联合Pk
和如果Pi={a
m_Pi = Dab * Dac * ... * Daz
最后,系数项是
c_P = \prod (#P1)! (#P2)! ... (#Pn)!
解决了这个问题后,我现在确定它属于on而不是这里。我没有遵循数学原理,但是如果知道di的大小是有界的,这不是你会使用哈希表甚至稀疏位数组编码的东西吗?只需迭代列表,在与di值对应的位置用“1”填充数据结构-如果它已经是1,则返回0。如果完成(n步),则返回1。它应该是O(n)。您正在尝试确定D是否包含任何重复项。最终,这要求您将每个条目相互比较,这只是列举两个元素的所有唯一组合。结果是
N*(N-1)/2
。您可以先对D进行排序,然后搜索重复的相邻对(O(N*log(N)
),或者,假设您坚持整数的有界范围,您可以使用位向量将其减少为线性时间,或者如果您喜欢冒险,则使用基数排序。这可能更适合DXY,就像真值表一样。对于D12*D13==1,您需要d1==d2和d1==d3,在这种情况下,d2==d3(即D23=1)为什么你要根据Dij-s来计算乘积,为什么不用di-s来计算呢?因为我想要一个通用表达式,以后可以用于很多不同的序列,我想1-D12-D13-D23+2 D12*D13
是对你的观点的回答。你能告诉我如何使用包含排除来找到最小表达式吗?我真的不知道那是什么。
m_Pi = Dab * Dac * ... * Daz
c_P = \prod (#P1)! (#P2)! ... (#Pn)!