1.计算机的核心概念
- 图灵论文《论数字计算在决断难题中的应用》是现代计算机科学的基石。他提出的图灵机概念成为了计算机理论的核心概念。
- 图灵机(Turing machine):A Turing machine is a simple
(abstract) device that can read from, write to, and move along an infinitely long strip of paper 实际中的机器有所不同,但都叫做有限状态机(finite state machine).
有限状态机(finite state machine):it has a finite set of states (some
of which indicate that it has finished), and every symbol it reads potentially triggers reading and/or
writing and switching to a different state. You can think of this machinery as a set of rules.
这些看似简单的机器完全的概述了计算机的本质。算法(Algorithm):An algorithm is a procedure, consisting of a finite set of steps (possibly including loops and
conditionals) that solves a given problem in finite time.- 图灵机就是一种模型,准确的描述算法解决问题的过程
现代计算机用存储器块取代了纸带,就是我们所熟知的内存(Random-Access machine) - 图灵机是一种抽象的简化的标准单处理计算机,并有以下特点:
1.顺序执行
2.标准的基础操作(例如算数,比较和内存存取)花费常量时间。
3.计算机字节(常量时间能够处理的值得大小)并不是无限制的。
决断难题(Entscheidungsproblem):David Hilbert提出的问题,是否存在一个算法来判断数学陈述的正确性
2.渐进符号
- O:上界
- Ω:下界
- Θ:上下综合
渐进时间复杂度的常见例子
复杂度 | 名称 | 例子 |
---|---|---|
Θ(1) | 常量时 | 哈希表的查找修改 |
Θ(lgn) | 对数 | 二插树搜索 |
Θ(n) | 线性 | 便利列表 |
Θ(nlgn) | 对数线性 | 最佳排序算法 |
Θ(n2) | 二次方 | n个对象相互比较 |
Θ(n3) | 三次方 | floyd-warshall最短路径算法 |
Θ(nk) | 多项式 | k层嵌套循环 |
Θ(kn) | 指数 | 处理n个元素的每个子集(k=2) |
Θ(n!) | 结成 | 处理n个值的每个顺序 |
三种重要的情况
1.最佳情况:
2.最坏情况
3.平均情况- 算法的经验评估
算法设计的目的是获得低的渐进运行时间(设计高效的算法),算法工程的目的是减少那个渐进复杂度下的隐藏的常量。
1.先用直接发解决问题,在考虑优化算法。
2.使用timeit
来计算时间
3.用分析工具来发现瓶颈
4.画下你的结果
5.在你以运行时间比较为基础做出结论时要当心随机误差。
for else
结构富国循环没有过早的被break终止,则执行else
的子句 3.实现图和树
3.1图的实现(临接表/临接矩阵)
2-1 A Straightforward Adjacency Set Representation
a, b, c, d, e, f, g, h = range(8) N = [ {b, c, d, e, f}, # a {c, e}, # b {d}, # c {e}, # d {f}, # e {c, g, h}, # f {f, h}, # g {f, g} # h ]
2-2 Adjacency Lists
a, b, c, d, e, f, g, h = range(8) N = [ [b, c, d, e, f], # a [c, e], # b [d], # c [e], # d [f], # e [c, g, h], # f [f, h], # g [f, g] # h ]
2-3 Adjacency dicts with Edge Weights
a, b, c, d, e, f, g, h = range(8) N = [ {b:2, c:1, d:3, e:9, f:4}, # a {c:4, e:3}, # b {d:8}, # c {e:7}, # d {f:5}, # e {c:2, g:2, h:2}, # f {f:1, h:6}, # g {f:9, g:8} # h ]
2-4 Dict with Adjacency Sets
N = { 'a':set('bcdef'), 'b':set('ce'), 'c':set('d'), 'd':set('e'), 'e':set('f'), 'f':set('cgh'), 'g':set('fh'), 'h':set('fg'), }
2-5 An Adjacency Matrix, Implemented with Nested Lists
a, b, c, d, e, f, g, h = range(8) # a b c d e f g h N = [[0,1,1,1,1,1,0,0], # a [0,0,1,0,1,0,0,0], # b [0,0,0,1,0,0,0,0], # c [0,0,0,0,1,0,0,0], # d [0,0,0,0,0,1,0,0], # e [0,0,1,0,0,0,1,1], # f [0,0,0,0,0,1,0,1], # g [0,0,0,0,0,1,1,0]] # h
2-6 A Weight Matrix with Infinite Weight for Missing Edges
a, b, c, d, e, f, g, h = range(8) _ = float('inf') # a b c d e f g h W = [[0,2,1,3,9,4,_,_], # a [_,0,4,_,3,_,_,_], # b [_,_,0,8,_,_,_,_], # c [_,_,_,0,7,_,_,_], # d [_,_,_,_,0,5,_,_], # e [_,_,2,_,_,0,2,2], # f [_,_,_,_,_,1,0,6], # g [_,_,_,_,_,9,8,0]] # h
3.2树的实现
2-7 A Binary Class
class Tree: def __init__(self, left, right): self.left = left self.right = right >>> t = Tree(Tree("a", "b"), Tree("c", "d")) >>> t.right.left 'c'
2-8 A Multiway Tree Class
class Tree: def __init__(self, kids, next=None): self.kids = self.val = kids self.next = next >>> t = Tree(Tree("a", Tree("b", Tree("c", Tree("d"))))) >>> t.kids.next.next.val 'c'
Bunch Pattern(一个灵活的类,允许你在构造器中制定任一属性)
class Bunch(dict): def __init__(self, *args, **kwds): super(Bunch, self).__init__(*args, **kwds) self.__dict__ = self >>> T = Bunch >>> t = T(left=T(left="a", right="b"), right=T(left="c")) >>> t.left {'right': 'b', 'left': 'a'} >>> t.left.right 'b' >>> t['left']['right'] 'b' >>> "left" in t.right True >>> "right" in t.right False
3.3图和树还有其他表示方法,具体的实现要结合具体的问题
哈希:为任意一个对象计算出一个整数
4.小心黑盒子(底层实现)
如果不知道底层实现可能会增加算法的时间复杂度。
例如:1.check in list and set
>>> from random import randrange >>> L = [randrange(10000) for i in range(1000)] >>> 42 in L False >>> S = set(L) >>> 42 in S False
由于list其实是array,所以对list进行check的时间复杂度是线性的,set是经过哈希的,所以对lset进行check的时间复杂度是常量时间。
2.构造字符串
>>> s = "" >>> for chunk in input(): ... s += chunk
它起作用,因为在python中做了一些聪明的优化,但是如果到达一定的大小,优化就会崩塌,时间复杂度就会上升到二次方。每一次
+=
操作都会创建一个新的字符串。一个更好的方法是:>>> chunks = [] >>> for chunk in input(): ... chunks.append(chunk) ... >>> s = ''.join(chunks)
更进一步的简化
>>> s = ''.join(input())
3.Floats的麻烦
float
的精度不高,在要求高精度的情况下请用decimal