最近,我参加了一次采访,面对有关哈希冲突的一个很好的问题。
问题:给定一个字符串列表,一起打印出字谜。
示例:
i / p:{行为,神,动物,狗,猫}
o / p:行为,猫,狗,神
我想创建哈希图并将单词作为键并将值作为字谜列表
为了避免冲突,我想为字谜生成唯一的哈希码,而不是对单词进行排序并将其用作键。
我正在寻找哈希算法,该算法除了使用链接外还可以解决冲突。我希望算法为act和cat生成相同的哈希码…,以便它将下一个单词添加到值列表中
谁能建议一个好的算法?
使用排序后的字符串进行哈希处理非常好,我可能已经做到了,但是确实很慢且麻烦。这是另一种想法,不确定是否可行- 选择一组尽可能小的素数,与字符集大小相同,并从字符到字符建立快速映射功能。然后对于给定的单词,将每个字符映射到匹配的质数中,然后相乘。最后,使用结果进行哈希处理。
这与Heuster提出的建议非常相似,只是发生了较少的碰撞(实际上,考虑到任意数量的素数分解的唯一性,我相信不会有错误的碰撞)。
简单例如-
int primes[] = {2, 3, 5, 7, ...} // can be auto generated with a simple code inline int prime_map(char c) { // check c is in legal char set bounds return primes[c - first_char]; } ... char* word = get_next_word(); char* ptr = word; int key = 1; while (*ptr != NULL) { key *= prime_map(*ptr); ptr++; } hash[key].add_to_list(word);
[编辑]
关于唯一性的几句话- 任何整数对素数的乘法都有一个分解,因此给定哈希中的整数键,您实际上可以重构所有可能对其进行哈希的字符串,仅这些单词即可。只需分解为素数,p1 ^ n1 * p2 ^ n2 * …并将每个素数转换为匹配的char。p1的char将出现n1次,依此类推。您无法获得未明确使用的任何新素数,成为素数意味着您无法通过其他素数的任何乘积来获得它。
这带来了另一个可能的改进- 如果可以构造字符串,则只需标记填充哈希时看到的排列。由于可以按字典顺序对排列进行排序,因此可以将每个数字替换为一个数字。这样可以节省将实际字符串存储在哈希中的空间,但是将需要更多的计算,因此不一定是一个好的设计选择。尽管如此,它还是原始问题的一个很好的复杂之处:)