我是一名程序员,但我还没有学过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字符串应该是相同的长度。但现在这并不重要。
答案 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)
。
但是,此算法实际上并不确定s1
和s2
是否为字谜。
如果您正在寻找实际解决问题的有效方法,请注意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。