一、概念
算法分析关心的是基于所使用的计算资源比较算法。
即我们总是希望用更少的计算资源得到同样的结果,而这里的计算资源有空间上的使用、时间上的使用、代码可读性等。
二、大O记法
对于一个函数,其时间函数可以估计为其基本语句的执行次数,参数n被称为问题规模。
常见的大O函数有:1(常数)、(对数)、
(线性)、
(对数线性)、
(平方)、
(立方)、
(指数)。
一般来说,谁在中起主导作用,就记为
。
示例:
异序值检测:如果一个字符串只是重 排了另一个字符串的字符,那么这个字符串就是另一个的异序词,比如 heart 与 earth,以及 python 与 typhon。为了简化问题,假设要检查的两个字符串长度相同,并且都是由 26 个英文字母的小写 形式组成的。我们的目标是编写一个布尔函数,它接受两个字符串,并能判断它们是否为异序词。
1、清点法
def anagramSolution1(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 = pos2 + 1
if found:
alist[pos2] = None
else:
stillOK = False
pos1 = pos1 + 1
return stillOK
对于上述算法,每检查一个s1中的字符,都需要遍历s2中所有字符。其时间函数可以表示为:
,在这个公式中
起着决定性作用,因此我们可以记作
。
2、排序法
def anagramSolution2(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 = pos + 1
else:
matches = False
return matches
上述代码通过对两个字符串进行排序再检查对应位置的字符是否相同来判断是否为异序词(其实有个漏洞,就是这里是默认两个字符串就是不一样的,如果是两个本来就相同的词,用此办法得出其就是异序词,实际上不是)。
乍一看,该算法的时间复杂度为,实际上,我们所调用的sort()方法是有代价的,其时间复杂度基本在
或
,也就是说,该算法的起决定性作用的是排序的时间复杂度。
3、蛮力法
蛮力法即穷尽所有的可能性,这里示例用蛮力法可以将s1中的字符生成所有可能的字符串再进行比对,26个字符串有种可能性,效率太低。
4、计数法
def anagramSolution4(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 = j + 1
else:
stillOK = False
return stillOK
该算法是将两个字符串ASCLL码值通过哈希表的形式存储下来,再去找对应的索引(值得注意的是,可能会有重复的字符出现,所以要对c1和c2进行+1操作)。
其时间复杂度函数
三、Python数据结构的性能
本章会对Python语言中的列表和字典进行损耗和收益分析,主要理解Python数据结构的效率。
1、列表
列表的常见操作有:索引、赋值以及加长列表。
一些实例会助于我们的理解:
这是四种生成数组的方式:
def test1():
l = []
for i in range(1000):
l = l + [i]
def test2():
l = []
for i in range(1000):
l.append(i)
def test3():
l = [i for i in range(1000)]
def test4():
l = list(range(1000))
使用time模块可以记录各个生成方式所花费的时间成本。通过观察我们可以得知第二种追加方式远快于第一种连接操作,而后面两种列表构造器range比追加方式更快了至少一倍。
下图是一些列表操作的大O效率:
2、字典
字典的常见操作有:取值、赋值以及包含(检查某个键是否在字典中)。
下图是字典操作的大O效率: