算法分析,哪一个是正确的?

时间:2014-11-11 17:25:51

标签: python algorithm

我是一名程序员,但我还没有学过CS,所以我对算法分析的理解很差。我正在读一本关于这个主题的书,我有一个问题:

假设我们有一个问题:给定两个字符串,我们需要理解第一个字符串是第二个字符串的字谜。

我的第一个解决方案是:

def anagram(s1, s2):
    for char in s1:
        if not char in s2:
            return False
    return True

在分析这样的算法时,我应该关心这段代码的复杂性吗?

if not char in s2

更准确的是,在搜索操作中使用哪种算法很重要,它将在for循环的每次迭代中执行?


Ps:对不起误解,我知道算法是错误的,因为anagram字符串应该是相同的长度。但现在这并不重要。

2 个答案:

答案 0 :(得分:4)

首先,您要分析每一行的复杂性(n, m = len(s1), len(s2),我将假设n > m):

def anagram(s1, s2):
    for char in s1: # O(n)
        if not char in s2: # O(m)
            return False # O(1)
    return True # O(1)

请注意,if not char in s2:O(m),因为在最糟糕的情况下,您必须检查s2中的每个字符,以确保char不存在。

然后你结合;如果您有嵌套操作,则整体复杂度为O(n * m)


正如评论中所指出的那样,您可以通过注意set的成员资格测试是O(1)(除了每个哈希冲突的地方,参见例如https://wiki.python.org/moin/TimeComplexity)来显着改进:

def anagram(s1, s2):
    s2 = set(s2) # O(m)
    for char in s1: # O(n)
        if not char in s2: # O(1)
            return False # O(1)
    return True # O(1)

通过将O(m)操作移出循环,可以将整体复杂度降低到O(n)

但是,此算法实际上并不确定s1s2是否为字谜。


如果您正在寻找实际解决问题的有效方法,请注意Python的排序(“Timsort”)是O(n log n)

def anagram(s1, s2):
    s1 = sorted(s1) # O(n log n)
    s2 = sorted(s2) # O(m log m)
    return s1 == s2 # O(m)

现在您没有嵌套,因此总复杂度为O(n log n)。这肯定比O(n)慢,但它具有工作的优势。

答案 1 :(得分:1)

这取决于您分析代码的内容。

如果您的问题是“搜索执行了多少次”,那么您无需担心“内部”的内容。

如果你的问题是关于全局算法的运行时间,那么是的,你必须担心'in'的运行时间。

这就是为什么当您使用C ++ STL容器时,您应该阅读手册中的时间复杂度。不幸的是,据我所知,这些信息不适用于Python。