1、算法的由来
(1)抽象的计算概念(能行可计算)
由有限数量的明确有限指令构成
指令执行在有限步后终止
指令每次执行都能获得唯一的结果
原则上可以由人单独采用纸笔完成,而不依靠其他辅助
每条指令可以机械性地被准确执行,不需要智慧和灵感
(2)图灵机计算模型
一条无限长的分格纸带,每格可以记录1个符号
一个读写头,可在纸带上左右移动,能读出和擦写格子的字符
一个状态寄存器,记录有限的状态中的1个状态
一系列有限的控 制规则:
读写头移动方法,是否改写,状态改变
2、算法和算法的复杂性
要考虑算法处理大数时的效率,所以需要考虑算法的复杂性
时间复杂度:用基本操作的重复次数作为计量单位
赋值语句是最合适的选择。
又是决定运行时间的不仅是问题规模,还有具体的数据也会影响运行时间
eg:排序时好的数据和坏的数据时间差距很大
常见O数量级 1 常数,log(n),n,n*log(n),n^2 , n3,2n
3、变位词的判断问题
变为词:两个单词的组成字母的是重新排序heart,earth
(1)解法一:逐一检查,存在就打个勾O(n**2)
(2)解法二:排序比较,先各自排序,再去逐个比较是否相同。排序步骤为主,O(nlog(n))
(3)解法三:暴力法,把f1的算有排列举出来,然后再看s2是否在其中 O(n!)
(4)计数比较
对比两个单词中26个字母的出现次数是否相同O(n),代价是需要更多的存储空间
4、python数据类型的性能
估算list和dict各种操作的时间数量级,可以通过运行时间的变化来判断
让最常用的操作性能最好(20%),牺牲不太常用的操作(80%)
v=a[i],a[i]=v O(1)
list.append(v) O(1)
lst=lst+ [v] O(n+k),k是被加列表的长度
使用timeit模块对函数进行计时
创建一个Timer对象,指定需要反复运行的语句和只需要运行一次的安装语句。然后反复调用这个对象的timeit方法,其中可以指定反复运行多少次。
eg:验证四种生成前n个整数列表的方法
参数"test1()"要反复运行的语句的字符串形式,第二个参数是只执行一次的语句的字符串形式,number试运行次数
第一种1.88s,二0.09s,三0.03s,四0.0097s
list常用操作的大O数量级
特别注意pop()与pop(i)数量级的差异,这也是为了让按索引取值和赋值最快
(1)先测出两个操作在每个列表大小下的时间
(2)通过改变列表的大小来测试两个操作的增长趋势
import timeit
popzero=timeit.Timer("x.pop(0)","from __main__ import x")
popend=timeit.Timer("x.pop()","from __main__ import x")
print "pop(0) pop()"
for i in range(1000000,100000001,1000000):
x=list(range(i))
pt=popend.timeit(number=1000)
x=list(range(i))
pz=popzero.timeit(number=1000)
print "%15.5f,%15.5f"%(pz,pt)
最后画成图再看
字典
最常用操作get 和set是O(1)