要展示不同数量级的算法,一个好例子就是经典的异序词检测问题。如果一个字符串只是重排了另一个字符串的字符,那么这个字符串就是另一个的异序词,比如 heart 与 earth ,以及 python 与 typhon 。
为了简化问题,假设要检查的两个字符串长度相同,并且都是由26个英文字母的小写形式组成的。我们的目标是编写一个布尔函数,它接受两个字符串,并能判断它们是否为异序词。
1、方案1:清点法
def anagram_solution1(s1, s2):
alist = list(s2)
pos1 = 0
stillOK = True
while pos1 < len(s1) and stillOK:
pos2 = 0
found = False
while pos2 < len(alist) and not found:
if s1[pos1] == alist[pos2]:
found = True
else:
pos2 += 1
if found:
alist[pos2] = None
else:
stillOK = False
pos1 += 1
return stillOK
print(anagram_solution1('heart', 'earth'))
通过分析可以给出公式:
∑
i
=
0
n
i
=
n
(
n
+
1
)
2
=
1
2
n
2
+
1
2
n
\sum_{i=0}^n i= \frac{n(n+1)}{2}=\frac{1}{2}n^2+\frac{1}{2}n
i=0∑n?i=2n(n+1)?=21?n2+21?n 当n增大时,起决定性作用的是
n
2
n^2
n2,而
1
2
\frac{1}{2}
21?可以忽略。故该方案的时间复杂度是
O
(
n
2
)
O(n^2)
O(n2)。
2、方案2:排序法
def anagram_solution2(s1, s2):
alist1 = list(s1)
alist2 = list(s2)
alist1.sort()
alist2.sort()
pos = 0
matches = True
while pos < len(s1) and matches:
if alist1[pos] == alist2[pos]:
pos += 1
else:
matches = False
return matches
print(anagram_solution2('heart', 'earth'))
表面上来看该算法的复杂度似乎是
O
(
n
)
O(n)
O(n),但由于调用了sort() 进行排序,排序时复杂度基本上是
O
(
n
2
)
O(n^2)
O(n2)或
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),所以排序操作起主导作用。
3、蛮力法
用蛮力解决问题的方法基本上就是穷尽所有的可能。就异序词检测问题而言,可以用
s
1
s1
s1中的字符生成所有可能的字符串,看看
s
2
s2
s2是否在其中。但这个方法有个难处。显然暴力是时间复杂度最高的算法,很多时候并不是最优先考虑的方向。
4、计数法
计数法顾名思义就是建立一个容纳所有元素的容器,例如这里是26个字母,记录每个字母出现的次数,然后进行比对。 总步骤数:
T
(
n
)
=
2
n
+
26
T(n)=2n+26
T(n)=2n+26 即:
O
(
n
)
O(n)
O(n)。
其中 ord() 函数作用是返回对应的 ASCII 数值,或者 Unicode 数值。
def anagram_solution4(s1, s2):
c1 = [0] * 26
c2 = [0] * 26
for i in range(len(s1)):
pos = ord(s1[i]) - ord('a')
c1[pos] = c1[pos] + 1
for i in range(len(s2)):
pos = ord(s2[i]) - ord('a')
c2[pos] = c2[pos] + 1
j = 0
stillOk = True
while j < 26 and stillOk:
if c1[j] == c2[j]:
j += 1
else:
stillOk = False
return stillOk
print(anagram_solution4('heart', 'earth'))
对上面方法进行封装
def anagram_solution4(s1, s2):
c1 = count1(s1)
c2 = count1(s2)
j = 0
stillOk = True
while j < 26 and stillOk:
if c1[j] == c2[j]:
j += 1
else:
stillOk = False
return stillOk
def count1(s):
c = [0] * 26
for i in range(len(s)):
pos = ord(s[i]) - ord('a')
c[pos] = c[pos] + 1
return c
print(anagram_solution4('heart', 'earth'))
|