第2章 算法分析
2.1 数学基础
利用函数间的大小关系来定义算法的相对增长率(relative rate of growth)。
定义:如果存在正常数 c c c和 n 0 n_0 n0使得当 N ≥ n 0 N≥n_0 N≥n0时 T ( N ) ≤ c f ( N ) T(N)≤cf(N) T(N)≤cf(N),则记为 T ( N ) = O ( f ( N ) ) T(N)=O(f(N)) T(N)=O(f(N))。(此时称 f ( N ) f(N) f(N)为 T ( N ) T(N) T(N)的上界(upper bound))
定义:如果存在正常数 c c c和 n 0 n_0 n0使得当 N ≥ n 0 N≥n_0 N≥n0时 T ( N ) ≥ c g ( N ) T(N)≥cg(N) T(N)≥cg(N),则记为 T ( N ) = Ω ( g ( N ) ) T(N)=Ω(g(N)) T(N)=Ω(g(N))。(此时称 g ( N ) g(N) g(N)为 T ( N ) T(N) T(N)的下界(lower bound))
定义:当且仅当 T ( N ) = O ( h ( N ) ) T(N)=O(h(N)) T(N)=O(h(N))且 T ( N ) = Ω ( h ( N ) ) T(N)=Ω(h(N)) T(N)=Ω(h(N))时, T ( N ) = Θ ( h ( N ) ) T(N)=Θ(h(N)) T(N)=Θ(h(N))。
定义:如果 T ( N ) = O ( p ( N ) ) T(N)=O(p(N)) T(N)=O(p(N))且 T ( N ) ≠ Θ ( p ( N ) ) T(N)≠Θ(p(N)) T(N)=Θ(p(N)),则 T ( N ) = o ( p ( N ) ) T(N)=o(p(N)) T(N)=o(p(N))。
对此定义进行数学推导,有以下3条结论。
法则1:如果 T 1 ( N ) = O ( f ( N ) ) T_1(N)=O(f(N)) T1(N)=O(f(N))且 T 2 ( N ) = O ( g ( N ) ) T_2(N)=O(g(N)) T2(N)=O(g(N)),那么
(a) T 1 ( N ) + T 2 ( N ) = m a x ( O ( f ( N ) ) , O ( g ( N ) ) ) T_1(N)+T_2(N)=max(O(f(N)),O(g(N))) T1(N)+T2(N)=max(O(f(N)),O(g(N)))。
(b) T 1 ( N ) ∗ T 2 ( N ) = O ( f ( N ) ∗ g ( N ) ) T_1(N)*T_2(N)=O(f(N)*g(N)) T1(N)∗T2(N)=O(f(N)∗g(N))。
法则2:如果 T ( N ) T(N) T(N)是一个 k k k次多项式,则 T ( N ) = Θ ( N 2 ) T(N)=Θ(N^2) T(N)=Θ(N2)。
法则3:对任意常数 k k k, log k N = O ( N ) \log^kN=O(N) logkN=O(N)。也就是说对数增长得非常缓慢。
可以通过计算极限 lim n → ∞ f ( N ) / g ( N ) \lim_{n\to \infty}f(N)/g(N) limn→∞f(N)/g(N)来确定两个函数的相对增长率。
- 极限是 0 0 0: f ( N ) = o ( g ( N ) ) f(N)=o(g(N)) f(N)=o(g(N))。
- 极限是 c ≠ 0 c≠0 c=0: f ( N ) = Θ ( g ( N ) ) f(N)=Θ(g(N)) f(N)=Θ(g(N))。
- 极限是 ∞ \infty ∞: g ( N ) = o ( f ( N ) ) g(N)=o(f(N)) g(N)=o(f(N))。
- 极限摆动:二者无关。
2.2 模型
假定一个模型机(有一个标准的简单指令系统 && 每条指令花费一个时间单元 && 32位 && 无限内存),今后都在此模型机上分析算法。
2.3 要分析的问题
要分析的最重要的资源一般就是运行时间。本书抛开硬件层面的差距,主要分析所使用的算法以及对该算法的输入。
其中,数据的读入一般是个瓶颈,一旦读入数据,问题就会迅速解决。我们需要使得算法足够有效而使其不致成为问题的瓶颈。
2.4 运行时间计算
一般法则
- 法则1——for循环:循环内语句的运行时间乘以迭代的次数。
- 法则2——嵌套的for循环:循环内语句的运行时间依次乘以迭代的次数。
- 法则3——顺序语句:取运行时间的最大值。
- 法则4——if/else语句:取if和else中运行时间较长者。
分析的基本策略:从内向外逐层进行分析。
书中案例分析提到一个重要概念:分治(divide-and-conquer):“分”:把问题分成两个大致相等的子问题,然后递归地对它们求解。“治”:将两个子问题的解合并到一起并可能再做些少量的附加工作,最后得到整个问题的解。
典例:二分查找、幂运算等,时间复杂度包含
O
(
log
N
)
O(\log N)
O(logN)。
书中案例分析提到另一个重要概念——联机算法(on-line algorithm):只对数据进行一次扫描,一旦完成对数组的读入和处理,就不再需要记忆它了。
仅需要常量空间并以
O
(
N
)
O(N)
O(N)速度运行的联机算法几乎是完美的算法。