第1章 绪论
1.1计算机与算法
计算时研究对象:规律、技巧
目标:高效、低耗。计算机是研究手段,计算是研究目标
- 计算模型=计算机=信息处理工具
- 所谓算法,即在特定计算模型下,旨在解决特定问题的指令序列
输入 待处理的信息(问题)
输出 经处理的信息(答案)
正确性 的确可以解决指定的问题
确定性 任一算法都可以描述为一个由基本操作组成的序列
可行性 每一基本操作都可实现,且在常数时间内完成
有穷性 对于任何输入,经有穷次基本操作,都可以得到输出
事实:程序!=算法
效率:速度尽可能快,存储空间尽可能少
1.2 计算模型
- 图灵机
- RAM
执行过程可以记录为一张表,表的行数即是所执行基本指令的总条数,能够客观度量算法的执行时间。图灵机、RAM模型为度量算法性能提供了准确的尺度。
1.3 大O记号
- 不含转向(循环、调用、递归),必须顺序执行,即是O(1)
- 对数O(logn),对数时间复杂度:该循环体之前、之内或者之后均只涉及常数次(逻辑判断、位与运算、加法、右移等)基本操作。用函数logn界定渐进复杂度时,常底数r的具体取值无所谓。这类算法虽不如常数复杂度算法理想,当从多项式的角度看仍能无限接近于后者,也是极为高效的一种算法。
- 多项式O(polynomial(n))
- 线性O(n)
- 指数O(2^n):算法的计算成本增长极快,通常被认为不可忍受
- 2-Subset问题是NP复杂度,就目前的计算模型而言,不存在多项式时间内回答此问题的算法。
1.4 算法分析
- 两个主要任务 = 正确性(不变性 x 单调性)+ 复杂度
- 级数:算术级数:与末项平方同阶;
d次幂级数求和,复杂度为O(n^d+1)
几何级数:以固定倍数,几何式增长求和,与末项同阶
收敛级数:O(1)
- 循环
- 封底估算:1天 = 24h60min60sec = 25*4000 = 10^5sec
1.5 迭代与递归
线性递归
- 数组求和:保证递归算法有穷性的基本技巧:判断并处理n=0之类的平凡情况,以免因无限递归而导致系统溢出。这类平凡情况称为“递归基”
- 线性递归
- 线性递归的模式,往往对应于所谓的减而治之的算法策略:递归每深入一层,待求解问题规模都缩减一个参数,直至最终蜕化为平凡的小问题。
递归分析
- 递归跟踪分析:检查每个递归实例,累计所需事件(调用语句本身,计入对应的子实例)其总和即算法执行时间。直观形象,仅适用于简明的递归模式。
整个算法所需的计算时间,应该等于所有递归实例的创建、执行和销毁所需的时间。其中,递归的创建和销毁均由操作系统负责完成,其对应的时间成本通常可以近似为常数,故往往可以忽略。我们只需计算各递归实例中非递归调用部分所需的时间。 - 递推方程:该方法无需绘出具体的调用过程,而是通过对递归模式的数学归纳,导出复杂度定界函数的递推方程(组)及其边界条件。间接抽象,更适用于复杂的递归模式
递归模式
- 多递归基:为保证有穷性,递归算法必须设置递归基,且确保总能执行到。为此,针对每一类可能出现的平凡情况,都需要设置对应的递归基,故同一算法的递归基可能(显式或隐式)不止一个。
- 多项递归:递归调用可能有多种可供选择的分支。
二分递归
- 分而治之
1.6 动态规划
- Fibonacci数:使用递归,复杂度为指数次幂。递归版fib()低效的根源在于,各递归实例均被大量重复地调用。
- fib()迭代:
解决方法A(记忆:memoization)将已计算过实例的结果制表备查
解决方法B(动态规划)颠倒计算方向:由自顶而下递归,为自底向上迭代。 - 最长公共子序列LCS:递归