了解anagram检测的线性运行时实现

时间:2015-12-07 02:21:38

标签: python algorithm big-o

我正在学习算法分析(python 2.7.6)。我正在读一本书(用算法和数据结构解决问题),其中Python是用于实现的语言。在第2章中,作者以非常清晰易懂的方式介绍了算法分析,并使用anagram检测程序作为模板来比较不同的运行时实现(quadratics,log linear,linear)。在线性且最有效的实现中,代码如下(我添加的注释):

def anagram_test2(s1,s2):
""" Checks if two strings are anagrams of each other
    Runs with O(n) linear complexity """

if (not s1) or (not s2):
    raise TypeError, "Invalid input: input must be string"
    return None

# Initialize two lists of counters         
c1 = [0] * 26
c2 = [0] * 26

# Iterate over each string
# When a char is encountered, 
# increment the counter at 
# its correspoding position   
for i in range(len(s1)):
    pos = ord(s1[i]) - ord("a")
    c1[pos] += 1

for i in range(len(s2)):
    pos = ord(s2[i]) - ord("a")
    c2[pos] += 1

j = 0
hit = True
while j < 26 and hit:
    if c1[j] == c2[j]:
        j += 1
    else:
        hit = False

return hit

我的问题是: 两个for循环之后的代码块是否可以用更简单的代码替换:

if c1 == c2:
    return True
else:
    return False

return 

哪里不需要迭代(而不是使用while语句)?使用第一种方法与第二种方法有一些计算/程序化原因吗?我在各种字符串组合上运行此版本,它的工作方式完全相同。

还有一个更普遍的问题: 作者类暗示嵌套迭代导致二次运行时,而非嵌套迭代导致线性/对数/对数线性运行时。是否有一套独特的规则来确定算法的运行时间?例如,如果没有嵌套迭代的程序,如何区分线性/对数线性/对数算法?在上面发布的示例之前的示例中,作者使用了排序和比较实现,其中没有嵌套循环,但承认sort方法有自己的成本,可以是log linear或quadratic。

3 个答案:

答案 0 :(得分:1)

在python中你可以做c1 == c2,但是其他语言需要一个循环,这就是作者试图展示的内容。

在python中,无论如何,单行代码对每个索引执行隐式for循环以检查是否相等。

答案 1 :(得分:0)

是的,所有这些代码都检查两个数组是否相等。要做到这一点,你可以做return c1 == c2

  

是否有一套独特的规则用于确定算法的运行时间   确定算法的运行时是一个复杂的过程,但可能有几个快捷方式。一些快捷方式是:

  • k嵌套循环从常量到n递增一个常量将在O(n^k)
  • 中运行
  • 从常量运行到n的循环,乘以常量将在O(log(n))
  • 中运行
  • 如果你有一个递归(在很多分而治之的算法中发生),你可以使用masters theorem来分析复杂性。对于非常难的递归,有一个Bazzi method.

P.S。与您的问题无关,但整个功能只能用counter代替。

from collections import Counter
def isAnagram(s1, s2):
    return Counter(s1) == Counter(s2)

答案 2 :(得分:0)

看起来作者试图用O(1)操作来拼出算法(这在尝试计算整体运行时复杂度时是有意义的。)

c1 == c2(其中c1和c2是列表)隐藏了相当多的复杂性;它实际上更像len(c1) == len(c2) and all(ch1 == ch2 for ch1,ch2 in zip(c1, c2))。他展示了比较中涉及的基本操作。