一、算法分析
- 目标:完成去粗存精的估算
- 最高境界:D
He calculated just as men breathe, as eagles sustain themselves in the air.
— Francois Arago
- 两个主要任务 = 正确性( 不变性 * 单调性 ) + 复杂度
- 复杂度分析的主要方法
- 迭代:级数求和
- 递归:递归追踪 + 递推方程
- 猜测 + 验证
二、级数
- 算数级数:与末项平方同阶
- T(n) = 1 + 2 + … + n = n(n+1)/2 = O(n^2)
- 幂方级数:比幂次高出一阶
- T(n) = 1^2 + 2^2 + … + n^2 = n(n+1)(2n+1) / 6 = O(n^3)
- 几何级数(a>1):与末项同阶
- T(n) = a^0 + a^1 + … + a^n = (a^n+1 -1) / (a - 1) = O(a^n)
- 收敛级数:O(1)
- 1/1/2 + 1/2/3 + 1/3/4 + … + 1/(n-1)/n = 1 - 1/n = O(1)
- 例:某段代码的迭代循环可以等效地描述为硬币的投掷过程,硬币投中正面的概论为a,这个程序运行的效果等效于不断地投掷这枚硬币,直到第一次出现反面,算法的复杂度取决于总共投掷了多少次硬币。
- 可能未必收敛但长度有限
- 调和级数:h(n) = 1 + 1/2 + 1/3 + … + 1/n = O(logn)
- 对数级数:log1 + log2 + log3 + … + logn = O(nlogn)
三、算法的证明
- 不变性-> 单调性 -> 正确性
- 示例:
void bubblesort( int A[], int n){
for(bool sorted = false; sorted = !sorted; n--)//逐趟扫描,直到完全有序
for(int i = 1; i<n; i++)//自左向右检查,逐对检查A[0, n)内各相邻元素
if(A[i-1] > A[i]){//若逆序,则交换相邻元素
swap(A[i-1], A[i]);
sorted = false;//同时清除逆序标志
}
}
- 不变性:经过k轮扫描交换后,最大的k个元素必然就位
- 单调性:经过k轮扫描交换后,问题规模缩减为n-k
- 正确性:经过至多n趟扫描后,算法必然终止,且能给出正确解答
四、封底估算(定量估算)
- 定义:几乎不需要笔或纸,而是在头脑中抓住问题的主要方面,可以快速的得出一个足够近似的估计。(用数学语言进行估计)
在三生三世中的一天相当于在一天中的一秒
1天 = 24h * 60 min * 60s = 10^5s
三生三世 = 300y = 3 * 100y * 365d = 3 * 3 * 10^4d = 10^10s