基于排序的anagram与基于Hash的anagram时间复杂度

时间:2018-02-20 18:14:41

标签: algorithm time-complexity

我现在两次采访中听到了以下问题:

给定一长串字符串,str_list和目标字符串,如果目标字符串是str_list中任何单词的字谜,则返回True

(假设有多个查询是可能的,所以我们不希望有早期退货或w / e的解决方案)

我已经实现了两次以下解决方案,我认为是O(NM),其中N是str_list的长度,M是str_list中最长字的长度。

def is_anagram(str_list,target):
    anagrams = set()
    #O(N)
    for s in str_list:
        #O(M)
        anagrams.add(frozenset(Counter(string).items()))

    #O(len(target), but we could just check length vs. longest str in str_list, so O(M))
    return frozenset(Counter(target).items()) in anagrams

    ##Total = O(N*M)

每次他们告诉我这是不错的,但我可以使用以下版本做得更好,使用排序:

def sorted_is_anagram(str_list,target):

    #O(N)
    for i,string in enumerate(str_list):
        #MLog(M)
        str_list[i] = "".join(sorted(string))

    #O(M*NLogN)
    str_list = set(sorted(str_list))

    #O(M(Log(M)))
    return "".join(sorted(target)) in str_list


    ##Total = O(N*MLog(M) + M*NLogN)

我疯了还是他们的版本根本不是更好?我搞砸了什么?

谢谢!

1 个答案:

答案 0 :(得分:1)

你可能误解了这个问题。通常,问题涉及一次给出大量字符串,然后针对该组字符串存在多个查询。因此,例如,您可能会获得一个包含250,000个英语单词的列表作为您的字符串集。然后,针对该列表将有数百万个查询。

解决方案涉及两个部分。首先,您创建一个字典,其中包含已排序的anagram作为其关键字。该值是可以由这些字母组成的单词列表。所以,给出“list”和“silt”这两个词,你就得到了:

{key="ilst", value={"list","silt"}}

您保存生成的字典,以便可以跨调用使用它。

现在,当某人进行查询时,您可以对给定单词中的字母进行排序,在字典中查找,然后使用字谜回复。

如果你给了N个平均长度为M的单词,那么构建字典就是O(N *(M log M))。但这是一次性成本。

每个查询都要求您对传递的单词中的字母进行排序,这也是O(M log M)。但字典查找是O(1)。因此K查询的成本是O(K *(M log M))。