Algorithm 为一组整数生成ID

Algorithm 为一组整数生成ID,algorithm,math,hash,Algorithm,Math,Hash,背景: 我正在研究整数序列{0,1,2…,n}的置换。 我有一个局部搜索算法,它以某种系统的方式将一个排列转换成另一个排列。该算法的要点是产生一个使代价函数最小化的置换。我喜欢处理范围广泛的问题,从n=5到n=400 问题是: 为了减少搜索工作量,我需要能够检查我以前是否处理过特定的整数排列。我正在使用一个哈希表,我需要能够为每个排列生成一个id,我可以将它用作表中的键。然而,我想不出任何好的哈希函数可以将一组整数映射到一个键中,这样冲突就不会发生得太频繁 我试过的东西: 我首先生成一个由n个素

背景:

我正在研究整数序列{0,1,2…,n}的置换。 我有一个局部搜索算法,它以某种系统的方式将一个排列转换成另一个排列。该算法的要点是产生一个使代价函数最小化的置换。我喜欢处理范围广泛的问题,从n=5到n=400

问题是:

为了减少搜索工作量,我需要能够检查我以前是否处理过特定的整数排列。我正在使用一个哈希表,我需要能够为每个排列生成一个id,我可以将它用作表中的键。然而,我想不出任何好的哈希函数可以将一组整数映射到一个键中,这样冲突就不会发生得太频繁

我试过的东西:

我首先生成一个由n个素数组成的序列,将排列中的第I个数乘以第I个素数,然后将结果相加。但是,即使对于n=5,结果关键帧也会产生碰撞

我还想将所有数字的值连接在一起,并将结果字符串的整数值作为键,但即使对于较小的n值,id也会很快变得太大。理想情况下,我希望能够将每个键存储为整数


stackoverflow对我有什么建议吗?

你可以用MD5散列一个包含整数的逗号分隔字符串

在C#中,它看起来像这样(免责声明:我今天使用的机器上没有编译器):


编辑:我在想什么?正如其他人所说,您不需要散列。CSV应该足够作为字符串Id(除非您的数字数组很大)。

将每个数字转换为字符串,连接字符串(通过StringBuffer)并将StringBuffer的内容作为键。

可能适合您。您需要创建一个随机整数的NxN矩阵,每个表示元素i的单元在当前排列中处于第j个位置。 对于给定的置换,您选择N个单元格值,并对它们逐个进行异或运算,以获得置换的密钥(请注意,密钥唯一性并没有得到保证)


该算法的要点是,如果您切换到置换中的元素,只需在新位置对旧的和xor进行异或运算,就可以轻松地从当前置换生成新密钥。

它需要多快

您可以将整数收集为字符串,然后对其进行散列,然后只获取前4个字节


对于散列,您可以使用任何函数,如MD5或SHA-256。

正如其他人所建议的,您可以使用散列生成一个高概率唯一的整数。但是,如果您需要整数始终是唯一的,则应该对排列进行排序,即为它们指定顺序。例如,集合{1,2,3}的常见排列顺序是字典顺序:

  • 1,2,3
  • 1,3,2
  • 2,1,3
  • 2,3,1
  • 3,1,2
  • 3,2,1
  • 在这种情况下,排列的id是其字典顺序索引。当然,还有其他排列排序的方法


    将ID设置为连续整数的范围,可以将处理后的置换存储为位字段或布尔数组。

    与问题没有直接关系,但作为一种替代解决方案,您可以将其用作查找结构。Trie树非常适合字符串操作,它的实现相对简单,对于大量长字符串,它应该比hashset更快(max of n(k),其中k是键的长度)。而且您的密钥大小也不受限制(例如在must int中的常规哈希集中,而不是更大)。在您的案例中,关键将是由一些字符分隔的所有数字组成的字符串。

    根据您的问题和您留下的评论,我认为您的问题不可能解决

    让我解释一下

    你说你需要从你的组合中得到一个唯一的散列,那么让我们制定规则#1:

    • 1:需要一个唯一的数字来表示任意数字/数字的组合
    好的,那么在一条评论中,您已经说过,由于内存限制,由于使用了相当多的数字,所以将它们存储为字符串或诸如此类的内容作为哈希表的键是不可行的。让我们把它改写成另一条规则:

    • 2:无法使用用于生成哈希的实际数据,因为它们不再在内存中
    基本上,您尝试获取一个较大的数字,并将其存储到一个更小的数字范围中,并且仍然具有唯一性

    对不起,你不能那样做

    典型的散列算法会产生相对唯一的散列值,因此,除非您愿意接受冲突,也就是说,一个新的组合可能会被标记为“已经看到”,即使它没有,那么您就倒霉了

    如果您尝试一个位字段,其中每个组合都有一个位,如果没有看到它,则为0,您仍然需要大量内存

    对于你在评论中留下的n=20的排列,你有20!(2432902008176640000)组合,如果您试图简单地将每个组合存储为位字段中的1位,则需要276589TB的存储空间


    你必须限制你要做的事情的范围。

    素数幂会起作用:如果
    p\u i
    是第i个素数,
    a\u i
    是元组的第i个元素,那么

    p_0**a_0 * p_1**a_1 * ... * p_n**a_n
    
    应该是唯一的。不过,这些数字将变得相当大:——)


    (例如,对于n=5,(1,2,3,4,5)将映射到870037764750,其已超过32位)

    类似于,似乎最好的方法是对排列具有确定性顺序。如果您按该顺序处理它们,则无需进行查找以查看您是否已经进行了任何特定的排列。

    获取同一系列数字{1,…,n}的两个排列,构造一个映射元组,(id,排列
    p_0**a_0 * p_1**a_1 * ... * p_n**a_n