Algorithm 在列表中查找重复项的最少检查

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 我的问题是: 为

给定一个序列(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
我的问题是:

  • 为什么D12*D13=D12*D23?这总是正确的(这意味着d序列是什么并不重要),但我真的不明白为什么,因为在我看来,这意味着D13=D23并不总是正确的(这取决于d序列)。这是有助于使表达式变小的关系

  • 我怎样才能找到所有这样的关系并得到一个最小表达式?上面的表达式是最小值吗?我甚至不知道


  • 我可以为你回答1。考虑这两种情况:

    案例1:
    D13=D23

    在这里,您可以将两边的
    D12
    相乘,得到
    D12*D13=D12*D23

    案例2:
    D13!=D23

    这意味着要么
    d1=d3
    XOR
    d2=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)!