我想要一个字典,为一组整数赋值。
例如key
为[1 2 3]
,value
具有一定的价值。
问题是[3 2 1]
在我的情况下需要被视为相同,所以如果我使用哈希方法,哈希需要相等。
该套装将有2到10个项目。
项目总和通常是固定的,因此我们不能根据总和制作哈希码,这是第一个自然的想法。
不是家庭作业,实际上在我的代码中遇到了这个问题。
这个集合在C#中基本上是IEnumerable<int>
所以任何数据结构都可以存储它们。
任何帮助表示赞赏。性能在这里也非常重要。
立即想到:我们可以总结一下items^2
并且已经获得了一些更好的哈希值,但我仍然希望听到一些想法。
编辑:嗯真的很抱歉,大家都建议订购,我没想到我需要说实际订购和散列是目前的解决方案我使用,我正在考虑更快的替代方案。
答案 0 :(得分:4)
基本上,这里的所有方法都是同一模板的实例化。将x 1 ,...,x n 映射到f(x 1 )op ... op f(x n ) ,其中op是某些集合X上的可交换关联操作,f是从项目到X的映射。此模板已被使用了几次,证明是好的。
在[1,p - 1]中选择随机大素数p和随机残基b。设f(x)= b x mod p,并将op加法。我们基本上将一个集合解释为多项式,并使用Schwartz–Zippel lemma来约束碰撞的概率(=非零多项式将b作为根mod p的概率)。
让op为XOR,让f为随机选择的表。这是Zobrist hashing,通过简单的线性代数参数最小化了预期的冲突次数。
模幂运算很慢,所以不要使用它。至于Zobrist散列,有300万个项目,表格f可能不适合L2,尽管它确实设置了一个主存储器访问的上限。
我会把Zobrist散列作为一个出发点,并寻找一个行为类似于随机函数的廉价函数f。这本质上是非加密伪随机生成器的工作描述 - 我会尝试通过用x播种快速PRG并生成一个值来计算f。
编辑:假设集合都具有相同的总和,不要选择f为1次多项式(例如,线性同余生成器的阶梯函数)。
答案 1 :(得分:2)
使用HashSet<T>
和HashSet<T>.CreateSetComparer()
,返回IEqualityComparer<HashSet<T>>
。
答案 2 :(得分:1)
我认为本文中提到的内容肯定会有所帮助:
http://people.csail.mit.edu/devadas/pubs/mhashes.pdf
增量多集散列函数及其在内存完整性检查中的应用
摘要:我们引入了一种新的加密工具:多重集散列函数。与将字符串作为输入的标准散列函数不同,多集散列函数在多集(或集)上运行。它们将任意有限大小的多重集合映射到固定长度的字符串(散列)。它们是渐进的,当新成员被添加到多集中时,散列可以在时间上与更改成比例地更新。这些函数可能是多重冲突抵抗的,因为它很难找到产生相同散列的两个多重集,或者只是设置冲突抵抗,因为它很难找到一个产生相同散列的集合和多集合。
答案 3 :(得分:1)
我认为你的平方思想正朝着正确的方向发展,但功能选择不佳。我会尝试更像PRNG函数或者只是乘以一个大素数,然后是所有结果值的XOR。
答案 4 :(得分:0)
一种可能性:对列表中的项进行排序,然后将其哈希。
答案 5 :(得分:0)
您可以对数字进行排序并从预定的索引中选择一个样本,如果当前值的数字较少,则将其余值保留为零。或者你可以把它们或其他任何东西弄清楚。
答案 6 :(得分:0)
为什么不喜欢
public int GetOrderIndependantHashCode(IEnumerable<int> source)
{
return (source.Select(x => x*x).Sum()
+ source.Select(x => x*x*x).Sum()
+ source.Select(x => x*x*x*x).Sum()) & 0x7FFFFF;
}
答案 7 :(得分:0)
如果key
中的值的范围恰好限于低位正整数,则可以使用简单查找将每个值映射到素数,然后将它们相乘以得到{{{ 1}}。
使用问题中的示例:
value
答案 8 :(得分:-1)
创建自己的实现IEnumerable<T>
的类型。
覆盖GetHashCode
。在其中,对您的收藏品进行排序,调用并返回ToArray().GetHashCode()
。