有效地分组字谜

Posted

技术标签:

【中文标题】有效地分组字谜【英文标题】:Grouping anagrams efficiently 【发布时间】:2015-12-25 07:34:34 【问题描述】:

我正在尝试编写一个程序,将列表中的所有字谜组合在一起,并且输出必须按字母顺序排序。我已经有一个程序可以使用 heapsort 在 O(nlog(n)) 时间内按字母顺序对输入进行排序。我的程序也对字谜进行分组,但是它太慢了。我相信使用散列会给出一个有效的算法,但不太确定如何实现它。有人对完成这项任务的有效算法有什么建议吗?

例如。

输入:

eat tea tan ate nat bat

输出:

ate eat tea

bat

nat tan

【问题讨论】:

你目前的(慢)分组算法是什么? 【参考方案1】:

看来你看错了。据我了解,您首先按字母顺序对字符串进行排序,然后尝试将它们分成组。

尝试反其道而行之。首先,将字符串分组为字谜,然后再对每个组进行排序。

可以通过多种方式对字谜进行分组,这里是其中之一:

    将每个字符串排序为一个字谜。这意味着,每个字谜本身都是排序的。例如:eat,tea,nat 都将被排序到字符串“aet”。 (记住每个单词的原始形式以备后用)。 一旦每个单词都经过“字谜排序”,您就可以简单地使用哈希表将它们全部分组,使用 Map<String,List<String>> - 其中键是“排序的字谜”,值是包含所有原始字词的列表字。 获得此映射后,您需要对作为此映射中的值的每个列表进行排序,这就是您的最终输出。

【讨论】:

【参考方案2】:

是的,它是散列。

您可以使用以下散列技术:(假设您的字符串都没有空格并且只有小写字符,如果它们是大写字母,则将被区别对待(cat 和 Act 不是字谜))

一个字符的哈希值将是它的ascii值的平方,即。

a = 97*97, b = 98*98, etc.

将每个单词的字符值加起来,就是它的哈希值。

现在,将具有相同(相等)哈希值的单词组合在一起。

PS:如果 cat 和 Act 是字谜,在计算之前将 A 转换为 a

PPS:为了响应@amit 的 cmets,我将每个字符的 ASCII 值平方以减少冲突,但是,这不会绝对没有冲突。您可以使用 n^th 斐波那契数的平方 作为哈希值,然后将它们相加。这进一步减少了碰撞。 因此,哈希值将类似于:

a = 98^2, b = 99^2, c = (98+99)^2, d = (b+c)^2 and so on...

【讨论】:

假设所有字符都是可行的,这对于 "d" (ascii=100) 和 "\n\n" (ascii=10 for each) 将失败。 一个单词不能有空格,只能是小写字符。 (假设) \n 算作空格。 一般来说,如果有一个唯一的素数是每个哈希码的一个因子,它就可以工作(这意味着,对于每个哈希码x,都有一个素数p,它是一个x 的因子,而不是每个哈希码 y!=x 的因子。 哦,更正。您将值相加,而不是多个值。这听起来更糟糕。例如 - 一个由 98*98 个字符组成的字符串,所有 a's 将具有与包含 97*97 个字符,所有 b's 的字符串相同的哈希码。

以上是关于有效地分组字谜的主要内容,如果未能解决你的问题,请参考以下文章

通过 Python 查找和分组字谜

对字谜词进行分组的算法

Java 8 Stream 函数将字谜列表分组为列表映射

有效地对重叠的矩形进行分组

有效地将函数并行应用于分组的 pandas DataFrame

你真的可以通过哈希有效地将相同的字符串分组吗?