我有一个非常特殊的问题要有效解决。
几何由V体积定义,从0到V-1编号。 每个体积由不同的表面界定,编号从0到N-1)。
Volume | Surfaces
--------------------
Geometry A (V=2, N=7): 0 | [0 3 5 6 2]
1 | [5 4 2 1]
2 | [4 0 1 3 6]
请注意,表面在一个体积中只会出现一次。 此外,一个表面最多包含2个几何体。
我对相同的基础几何有两种不同的描述,我想找到几何A中的哪个体积与几何B中的哪个体积相对应。换句话说,我具有相同的N个曲面,但是V体积的定义不同。
这是一个可能与上面的几何A相对应的几何B:
Volume | Surfaces
--------------------
Geometry B (V=2, N=7): 0 | [1 5 4 2]
1 | [3 6 5 0 2]
2 | [0 1 3 6 4]
鉴于几何A和B,我希望能够尽可能高效地将几何A的每个体积绑定到几何B中的相应体积。
A 0 1 2
B 1 0 2
按升序或降序对每个表面数组进行排序,而不是按照其表面的字典顺序对每个体积进行排序。通过这种方式可以轻松,可靠地解决该问题。
为每个数组计算一个快速,唯一的哈希,而不是对该哈希之后的卷进行排序。哈希不应该取决于数组中曲面的顺序。
获取哈希(卷)=分钟([表面])
此哈希最多已发生1次碰撞,因为一个表面只能出现在2个体积中!
现在,如果我采用hash(Volume)= min([Surfaces])+ max([Sufaces])* N,我仍然最多发生1次碰撞,但是当存在大量体积时,发生的概率非常小和表面。
答案 0 :(得分:2)
如上所述,您的解决方案非常适合您的需求。但是,如果您寻求完美的哈希函数,则可以使用以下方法:
假设p_i是第i个素数,使得p_0 = 2,p_1 = 3,p_2 = 5,p_3 = 7,p_4 = 11,p_5 = 13,p_6 = 17,p_7 = 19...。可以在数组中的x_0,x_1,...,x_k上定义哈希函数,使得h(x_0,...,x_k)= p_ {x_0} p_ {x_1} ... p_ {x_k}。同样,对于重复数,我们可以将重复数作为p_ {x_i}的幂。这意味着,例如,如果x_i重复3次,则
h
中p_ {x_i}的幂将为p_ {x_i} ^ 3。如果x_i的重复次数为a_i,则将有h(x_0,...,x_k)= p_ {x_0} ^ {a_0} p_ {x_1} ^ {a_1} ... p_ {x_k} ^ {a_k}。
因此,对于几何A,我们有:
Volume | Surfaces | Hash
----------------------------------
geometry A 0 | [0, 3, 5, 6, 2] | 2 * 7 * 13 * 17 * 5 = 15470
1 | [5, 4, 2, 1] | 13 * 11 * 5 * 3 = 2145
2 | [4, 0, 1, 3, 6] | 11 * 2 * 3 * 7 * 17 = 7854
以及类似的几何B方法。由于此函数为每个数组返回一个唯一值(与顺序无关),因此可以使用对应的哈希值排列曲面。如果N
的值不大,则可以使用素数的预先计算的列表。
答案 1 :(得分:0)
我发现了一个很好的哈希函数,该函数几乎永远不会发生冲突:
V: [S_0 S_1 S_2 S_3...S_N-1]
u64 hash(V) = 0;
for i in {0..N-1} :
hash(V) = hash(V) ^ (1<<(S_i & 63))
end
这提供了一个唯一的64位数字,并且所有数字都是可能的(与Omg的解决方案不同,鉴于表面列表中没有重复,因此大多数数字都无法获得)
在发生冲突的极端情况下(排序后将看到),我将以愚蠢的方式按字典顺序比较数组。