给定一个字符串数组,返回所有的字谜字符串组

Posted

技术标签:

【中文标题】给定一个字符串数组,返回所有的字谜字符串组【英文标题】:Given a string array, return all groups of strings that are anagrams 【发布时间】:2012-01-22 06:15:20 【问题描述】:

我的解决方案:

对数组中的每个字符串单词,排序O(m lg m),m是单词的平均长度。

建立一个哈希表

将排序好的单词作为key放入哈希表,同时生成单词的所有排列(O(m!)),用O(m)在字典(前缀树映射)中搜索每个排列,如果是在字典中,将它(O(1))放入哈希表中,以便所有排列后的单词都放入具有相同键的列表中。

总共 O(n * m * lg m * m!) 时间和 O(n* m!) 空间,n 是给定数组的大小。

如果 m 很大,则效率不高,m! .

有更好的解决方案吗?

谢谢

【问题讨论】:

【参考方案1】:

我们定义了一个字母表,其中包含我们单词表中可能存在的每个字母。接下来,我们需要为字母表中的每个字母使用不同的质数,我建议使用你能找到的最小的。

这将为我们提供以下映射: a => 2, b => 3, c => 5, d => 7 等

现在将您要表示的单词中的字母计数为整数,并按如下方式构建结果整数:

伪代码:

result = 1
for each letter:
....result *= power(prime[letter], count(letter,word)

一些例子:

aaaa => 2^4

aabb => 2^2 * 3^2 = bbaa = baba = ...

等等。

因此,您将有一个整数表示字典中的每个单词,并且您要检查的单词将能够转换为整数。因此,如果 n 是您的单词列表的大小,k 是最长单词的大小,则构建新词典需要 O(nk) 时间,检查新单词需要 O(k) 时间。

Hackthissite.com 的编程挑战是:给定一个打乱的单词,在字典中查找它的字谜是否在字典中。有一个good article 是我借用答案的问题的有效解决方案,它还详细介绍了进一步的优化。

【讨论】:

我们还应该考虑构建字母 O(sizeof(dictionary) * k) 的成本。在您的解决方案中, O(nk) 用于给定的字符串数组而不是字典。谢谢 是的,我应该在那里更清楚,n 是字典的大小,给定的字符串数组可能是 l,然后一旦字典建成,运行时间就会 O(lk) 这是一个疯狂的解决方案。使用您的方案,“pizza”一词的值大于 9.6 e19。您的值会经常超出 64 位数字的范围,并且有些英文单词会超出 128 位数字的范围。你最好使用字符串键。【参考方案2】:

使用计数排序对单词进行排序,以便在 O(m) 中完成排序。 排序后从单词生成键并将节点(键,值)插入哈希表。生成密钥可以在 O(m) 内完成。

您可以将 (key,value) 中的值作为可以容纳多个字符串的动态数组。 每次插入一个已经存在的键时,只需将生成键的原始单词推送到值数组上。

所以总体时间复杂度为 O(mn),其中 n 是单词的总数(输入的大小)。

此链接也有解决类似问题的方法-> http://yourbitsandbytes.com/viewtopic.php?f=10&t=42

【讨论】:

【参考方案3】:
#include <map>
#include <iostream>
#include <set>
#include <algorithm>

int main () 
  std::string word;
  std::map<std::string, std::set<std::string>> anagrams;
  while(std::cin >> word) 
    std::string sortedWord(word);
    std::sort(sortedWord.begin(), sortedWord.end());
    anagrams[sortedWord].insert(word);
  
  for(auto& pair : anagrams) 
    for(auto& word : pair.second) 
      std::cout << word << " ";
    
    std::cout << "\n";
  

我会让比我更擅长大 O 分析的人弄清楚其中的复杂性。

【讨论】:

m - 任何字符串中的最大字符数,n - 字符串总数。 m * log m 用于对每个字符串进行排序。 m * log n 用于插入anagrams。 m 因子,因为每个字符串比较都需要 O(m) 时间。因此,O(n * m * (log n + log m)) 是一个上限。【参考方案4】:

将字典转换为一个单词的排序字符的映射,映射到这些字符的每个单词并存储它。对于给定的每个单词,对其进行排序并将映射中的字谜列表添加到您的输出中。

【讨论】:

【参考方案5】:

我不相信你可以在 O 方面做得比

对每个单词的字母进行排序 对已排序的单词列表进行排序 现在将连续分组每组字谜。

【讨论】:

以上是关于给定一个字符串数组,返回所有的字谜字符串组的主要内容,如果未能解决你的问题,请参考以下文章

需要帮助来理解字谜代码的乐趣

检查字符串是不是是字谜

给定一些文本输入,找到最大的字谜组

算法:按字典顺序在给定索引处查找给定字符串的字谜

代码高尔夫:查找所有字谜

字符串数组只包含字谜?