了解变位词检测的线性运行时实现
Understanding a linear runtime implementation of anagram detection
我正在学习算法分析(python 2.7.6)。我正在读一本书(使用算法和数据结构解决问题),其中 Python 是用于实现的语言。在第 2 章中,作者以非常清晰易懂的方式介绍了算法分析,并以一个变位词检测程序为模板来比较不同的运行时实现(二次方、对数线性、线性)。线性的,最高效的实现,代码如下(注释是我加的):
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 语句相反)?使用第一种方法与第二种方法有一些 computational/programmatic 原因吗?我 运行 这个版本在各种字符串组合上都完全一样。
还有一个更笼统的问题:
作者有点暗示嵌套迭代会导致二次运行时间,而非嵌套迭代会导致 linear/logarithmic/log 线性运行时间。是否有一套独特的规则来确定算法的运行时间?例如,给定一个没有嵌套迭代的程序,如何区分 linear/log linear/log 算术算法?在我上面发布的示例之前的示例中,作者使用了一种没有嵌套循环的排序和比较实现,但承认排序方法有其自身的成本,即对数线性或二次。
是的,这段代码所做的就是检查两个数组是否相等。为此,您只需 return c1 == c2
Is there a distinct set of rules for determining an algorithm's runtime
Figuring out the runtime of the algorithm is a complex procedure, but there can be a couple of shortcuts. Some of the shortcuts are:
k
从常数 运行 到 n
以常数递增的 运行 嵌套循环将在 O(n^k)
中 运行
- 一个从常数 运行 到
n
的循环,你乘以一个常数将 运行 in O(log(n))
- 如果你有递归(这发生在很多分而治之的算法中),你可以使用 masters theorem. For really hard recursions there is a Bazzi method.
来分析复杂性
P.S. 与您的问题无关,但整个功能可以只用 counter.
代替
from collections import Counter
def isAnagram(s1, s2):
return Counter(s1) == Counter(s2)
在python中你可以做c1 == c2
,但是其他语言需要一个循环,这就是作者试图展示的。
在 python 中,那一行代码对每个索引执行隐式 for 循环以检查是否相等。
看起来作者正试图根据 O(1) 操作来阐明算法(这在试图计算出整体运行时复杂度时很有意义)。
c1 == c2
(其中 c1 和 c2 是列表)隐藏了相当多的复杂性;它实际上更像 len(c1) == len(c2) and all(ch1 == ch2 for ch1,ch2 in zip(c1, c2))
。他展示了比较中涉及的基本操作。
我正在学习算法分析(python 2.7.6)。我正在读一本书(使用算法和数据结构解决问题),其中 Python 是用于实现的语言。在第 2 章中,作者以非常清晰易懂的方式介绍了算法分析,并以一个变位词检测程序为模板来比较不同的运行时实现(二次方、对数线性、线性)。线性的,最高效的实现,代码如下(注释是我加的):
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 语句相反)?使用第一种方法与第二种方法有一些 computational/programmatic 原因吗?我 运行 这个版本在各种字符串组合上都完全一样。
还有一个更笼统的问题: 作者有点暗示嵌套迭代会导致二次运行时间,而非嵌套迭代会导致 linear/logarithmic/log 线性运行时间。是否有一套独特的规则来确定算法的运行时间?例如,给定一个没有嵌套迭代的程序,如何区分 linear/log linear/log 算术算法?在我上面发布的示例之前的示例中,作者使用了一种没有嵌套循环的排序和比较实现,但承认排序方法有其自身的成本,即对数线性或二次。
是的,这段代码所做的就是检查两个数组是否相等。为此,您只需 return c1 == c2
Is there a distinct set of rules for determining an algorithm's runtime Figuring out the runtime of the algorithm is a complex procedure, but there can be a couple of shortcuts. Some of the shortcuts are:
k
从常数 运行 到n
以常数递增的 运行 嵌套循环将在O(n^k)
中 运行
- 一个从常数 运行 到
n
的循环,你乘以一个常数将 运行 inO(log(n))
- 如果你有递归(这发生在很多分而治之的算法中),你可以使用 masters theorem. For really hard recursions there is a Bazzi method. 来分析复杂性
P.S. 与您的问题无关,但整个功能可以只用 counter.
代替from collections import Counter
def isAnagram(s1, s2):
return Counter(s1) == Counter(s2)
在python中你可以做c1 == c2
,但是其他语言需要一个循环,这就是作者试图展示的。
在 python 中,那一行代码对每个索引执行隐式 for 循环以检查是否相等。
看起来作者正试图根据 O(1) 操作来阐明算法(这在试图计算出整体运行时复杂度时很有意义)。
c1 == c2
(其中 c1 和 c2 是列表)隐藏了相当多的复杂性;它实际上更像 len(c1) == len(c2) and all(ch1 == ch2 for ch1,ch2 in zip(c1, c2))
。他展示了比较中涉及的基本操作。