文章目录
2 算法效率分析基础
算法分析主要是指算法效率分析,原因有二:算法效率可精确定量研究;算法特性中最重要的。
本章内容结构如下:
- 算法效率分析的通用框架
- 算法效率的符号表示
- 非递归算法的效率分析
- 递归算法的效率分析
- 特殊递归算法-斐波那契:无法计算效率
- 其余分析算法的方法(除3、4所用的数学表示):经验分析和可视化分析
2.1 通用框架
算法效率包括时间和空间,本章主要以时间为例,空间采用类似方法。
如何衡量算法效率?
- 算法效率受什么影响?计算机性能、输入规模
- 用什么衡量?运行时间、运行次数
- 对于任何输入,效率均相同?
根据以上问题依次回答。
输入规模
算法效率定义:一个以输入规模n为参数的函数
如何度量输入规模:
-
考虑算法输入的类型:
两个矩阵相乘的输入规模:第一种是矩阵的阶数n;第二种是矩阵(非方矩阵)中元素个数。
-
考虑算法细节:
拼写检查:一是英文字符个数;二是中文字符个数。
判断一个数是否为质数:数的二进制位数??
运行时间
基本操作的执行次数C(n)
,一般为循环内层的操作。
耗时操作:除法最耗时–>乘法–>加法或减法
对于大规模输入,效率分析主要关注增长次数及其常数倍, 故算法效率公式可忽略乘法常量。
什么是增长次数和常数倍?
比如顺序查找,效率为 1 2 n 2 \frac{1}{2} n^2 21n2,若规模增长为 m = 2 n m=2n m=2n,则增长倍数为 1 2 ( 2 n ) 2 / 1 2 n 2 = 4 \frac{1}{2} (2n)^2 / \frac{1}{2} n^2 = 4 21(2n)2/21n2=4,或者 1 2 m 2 / 1 2 ( 1 / 2 ∗ m ) 2 = 4 \frac{1}{2} m^2 / \frac{1}{2} (1/2*m)^2 = 4 21m2/21(1/2∗m)2=4,增长次数为 1 2 ∗ 3 n 2 \frac{1}{2}*3n^2 21∗3n2,或者 1 2 ∗ 3 / 4 m 2 \frac{1}{2}*3/4 m^2 21∗3/4m2
反复领悟 :若规模为 m = n 2 m = n^2 m=n2,则增长倍数为原来的 m m m倍,增长次数为 n 4 − n 2 n^4 - n^2 n4−n2,以当前规模为参数,则增长次数为 m 2 − 1 m^2-1 m2−1,仍属于 O ( n 2 ) O(n^2) O(n2), n n n表示当前输入规模,不是某个固定值。
综上:增长倍数比较好理解,增长次数等同于增长倍数
l o g a n = l o g a b l o g b n log_an = log_ab log_bn logan=logablogbn
根据上述公式发现,不同的底数,对数函数的变化仅是一个常量,不影响算法效率的计算。
import math
math.log(4,2) == math.log(4,3)*math.log(3,2)
不同类型输入
算法运行时间不仅取决于输入规模,还取决于输入细节。
以顺序查找为例,在数组arr[1,…,n]中查找元素:
- 若查找元素即arr[1],则只需比较一次;最优效率
- 若查找元素为arr[n]或不在数组中,则需比较n次;最坏效率
- 若查找元素处于arr任意位置;平均效率
同一规模不同类型的输入,其效率亦不同。
摊销效率:求不相交集合并集时说明
Exercise 2.1
1 分析算法
-
计算n个数的和
- 输入规模:n
- 基本操作:求和
- 不同类型的输入,效率相同
-
计算n!
- 输入规模:n
- 基本操作:相乘
- 不同类型输入,效率相同
-
n个数字中最大元素
- 输入规模:n
- 基本操作:比较
- 不同类型输入:效率相同
-
欧几里得算法
- 输入规模:??
- 基本操作:求余
- 效率相同
-
埃拉托色尼筛选法
- 输入规模:数值n,首先会生成一个[2,…,n]的列表
- 基本操作:相乘
- 效率相同
-
两个n位十进制数相乘的笔算算法
-
输入规模:十进制位数
-
基本操作:除以10
-
效率相同
-
代码
def multipy(a,b): if a==0 or b==0: return 0 s = 0 # 记录相乘结果 l = 1 #记录a进行除法次数 while a: p = a%10 t = 1 #记录t进行除法次数 while b: m = b%10 s = s+p*m*(10**l)*(10**t) b = b/10 t = t+1 a = a/10 l = l+1 return s
效率分析:
输入规模:十进制位数
基本操作:主要是两个数除以10,或者相加,或者相乘,根据运行时间,除法最耗时,故基本操作为除法。
时间效率:一个数为n位十进制,则进行n次除以10,两个数则为n*n次除以10
-
2关于矩阵的算法
-
矩阵相加
基本操作:相加
执行次数:矩阵为n阶方阵 - n*n次;矩阵元素n个 - n次
-
矩阵相乘
基本操作:相乘
执行次数:矩阵为n阶方阵 - n*n次;矩阵元素n个 - n次
总结:矩阵操作次数主要依赖于元素个数。
3 查找键在列表中出现次数:
count(arr,target):
# 在arr中计算target的出现次数
# n为arr的长度
count = 0
for i=1,...,n:
if arr[i] == target:
count ++
return count
输入规模:数组元素个数n
基本操作:比较
不同类型的输入:效率相同
效率:比较n次
4 不同类型的输入
-
选择手套:每次选一只手套,取出不放回,直至出现成对手套
最好情况:选2只手套即匹配
最差情况:3种颜色各一只,则第4只一定成对,故4只。
-
丢失的袜子
不懂
5 数学特性
-
以下公式代表十进制正整数用二进制表示时的位数,二进制位数是指第一位不为0的情况
b = ⌊ log 2 n ⌋ + 1 b = \lfloor \log_2 n \rfloor + 1 b=⌊log2n⌋+1
3位二进制数代表范围为[4,7] (2^3-1),2位二进制数代表范围为[2,4];b代表二进制位数,n表示十进制数
2 b − 1 ≤ n ≤ 2 b − 1 ⌈ log 2 ( n + 1 ) ⌉ ≤ b ≤ ⌊ log 2 n ⌋ + 1 b = ⌊ log 2 n ⌋ + 1 2^{b-1} \leq n \leq 2^b-1 \\ \lceil \log_2 (n+1) \rceil \leq b \leq \lfloor \log_2 n \rfloor +1 \\ b = \lfloor \log_2 n \rfloor +1 2b−1≤n≤2b−1⌈log2(n+1)⌉≤b≤⌊log2n⌋+1b=⌊log2n⌋+1 -
问题1已证明
-
十进制位数
1 0 b − 1 ≤ n ≤ 1 0 b − 1 ⌈ log 10 ( n + 1 ) ⌉ ≤ b ≤ ⌊ log 10 n ⌋ + 1 b = ⌊ log 10 n ⌋ + 1 10^{b-1} \leq n \leq 10^b-1 \\ \lceil \log_{10} (n+1) \rceil \leq b \leq \lfloor \log_{10} n \rfloor +1 \\ b = \lfloor \log_{10} n \rfloor +1 10b−1≤n≤10b−1⌈log10(n+1)⌉≤b≤⌊log10n⌋+1b=⌊log10n⌋+1 -
原因:不知
6 不知,扩充什么??
7 高斯消去法, 1 3 n 3 \frac{1}{3} n^3 31n3次乘法运算
- 8倍, n = 500 , 2 n = 1000 n=500,2n=1000 n=500,2n=1000
- 相同时间,新计算机求解方程个数为原来的10倍 n 3 ∗ 1000 = b 3 , b = 10 ∗ n n^3 * 1000 = b^3,b=10*n n3∗1000=b3,b=10∗n
8 new_n = 4*n:增长2次,增长2倍,增长4倍,增长16倍,增长64倍,增长2^n的3次方
综上,可见2^n级算法增长倍数为指数级,应避免对大规模输入用该类算法。
9 大致相同,精确来说是小;小;相同;相同;相同;小
10 总共麦粒为
2 0 + 2 1 + . . . + 2 64 = ( 2 64 − 1 ) ∗ 65 2^0 + 2^1 +...+2^{64} = (2^{64}-1)*65 20+21+...+2