算法-02-算法分析与设计

24 年 4 月 9 日 星期二
1467 字
8 分钟

算法分析与设计

为什么要分析算法?

  • 按难度对问题和算法进行分类
  • 预测性能,比较算法,调整参数
  • 更好地理解和改进实现和算法

算法分析

问题:

  • 正确性 (Correctness)
  • 时间效率 (time efficiency)
  • 空间效率 (space efficiency)
  • 最优性 (optimality)

方法:

  • 实证分析 (Empirical analysis)
  • 理论分析 (Theoretical analysis)

运行时间

程序的运行时间通常取决于输入规模,并随输入规模的增加而增加。

时间效率的实证分析

  1. 编写实现算法的程序
  2. 使用各种输入规模运行程序(例如,500、1000、2000等)
  3. 测量实际运行时间(例如,在C/C++中使用clock()函数)
  4. 绘制结果图表

时间效率的理论(Theoretical)分析

影响运行时间的两个主要因素:

  1. 执行每个操作的成本(Cost) 取决于机器、编译器
  2. 每个操作的执行频率(Frequency) 取决于算法、输入数据

时间效率是通过计算其基本操作执行的次数来衡量的, o作为输入规模的函数。 "用一个关于输入规模nn的函数f(n)f(n)来表示算法的时间效率,其中f(n)f(n)表示算法执行基本操作的次数。"

  • 基本操作:对算法运行时间贡献最大的操作(例如,算法最内层循环中最耗时的操作)
  • 近似计算copc_{op}C(n)C(n)(忽略低阶项)

最佳情况、平均情况和最坏情况

对于某些算法,效率取决于输入的形式:

  • 最坏情况:Cworst(n)C_{worst}(n) - 在大小为nn的输入上执行基本操作的最大次数
  • 最佳情况:Cbest(n)C_{best}(n) - 在大小为nn的输入上执行基本操作的最小次数
  • 平均情况:Cavg(n)C_{avg}(n) - 在大小为nn的典型输入上执行基本操作的"平均"次数

增长的阶

假设C(n)=12n(n1)C(n) = \frac{1}{2}n(n-1),如果计算机的速度提高一倍,算法将运行多快?如果问题规模增加一倍,需要多长时间来求解?

关键因素:

  • 不是给定nn时执行的基本操作的确切数量
  • 而是随着nn的增加,基本操作的数量如何增长

忽略常数因子、常数和小输入规模,关注nn \to \infty时的增长阶数。

渐近增长阶数

  • 比较函数的方法,忽略常数因子小输入规模
  • 根据增长率对函数进行分类
    • O(g(n))O(g(n)):大O符号 - 增长速度不超过g(n)g(n)的函数f(n)f(n)类(最坏情况的上界
    • Θ(g(n))\Theta(g(n)):大Θ\Theta符号 - 增长速度与g(n)g(n)相同的函数f(n)f(n)类(最佳情况
    • Ω(g(n))\Omega(g(n)):大Ω\Omega符号 - 增长速度至少与g(n)g(n)一样快的函数f(n)f(n)类(最坏情况的下界

大O符号(OO-notation)

上界。如果存在常数c>0c > 0n00n_0 \geq 0,使得对于所有nn0n \geq n_0,有t(n)cg(n)t(n) \leq c \cdot g(n),则t(n)t(n)O(g(n))O(g(n))

例如,t(n)=100n+5t(n) = 100n + 5,证明t(n)O(n2)t(n) \in O(n^2)

证明:对于所有n1n \geq 1,有100n+5100n2+5n2=105n2100n + 5 \leq 100n^2 + 5n^2 = 105n^2(即取c=105c = 105n0=1n_0 = 1)。因此,t(n)O(n2)t(n) \in O(n^2)

Ω\Omega符号(Ω\Omega-notation)

下界。如果存在常数c>0c > 0n00n_0 \geq 0,使得对于所有nn0n \geq n_0,有t(n)cg(n)t(n) \geq c \cdot g(n),则t(n)t(n)Ω(g(n))\Omega(g(n))

例如,t(n)=n3t(n) = n^3,证明t(n)Ω(n2)t(n) \in \Omega(n^2)

证明:对于所有n0n \geq 0,有n3n2n^3 \geq n^2(即取c=1c = 1n0=0n_0 = 0)。因此,t(n)Ω(n2)t(n) \in \Omega(n^2)

Θ\Theta符号(Θ\Theta-notation)

紧界。如果存在常数c1>0c_1 > 0c2>0c_2 > 0n00n_0 \geq 0,使得对于所有nn0n \geq n_0,有c2g(n)t(n)c1g(n)c_2 \cdot g(n) \leq t(n) \leq c_1 \cdot g(n),则t(n)t(n)Θ(g(n))\Theta(g(n))

例如,t(n)=12n(n1)t(n) = \frac{1}{2}n(n-1),证明t(n)Θ(n2)t(n) \in \Theta(n^2)

证明:对于所有n0n \geq 0,有12n(n1)=12n212n12n2\frac{1}{2}n(n-1) = \frac{1}{2}n^2 - \frac{1}{2}n \leq \frac{1}{2}n^2(上界)。对于所有n2n \geq 2,有12n(n1)=12n212n12n212n14n2\frac{1}{2}n(n-1) = \frac{1}{2}n^2 - \frac{1}{2}n \geq \frac{1}{2}n^2 - \frac{1}{2}n \geq \frac{1}{4}n^2(下界)(即取c2=14c_2 = \frac{1}{4}c1=12c_1 = \frac{1}{2}n0=2n_0 = 2)。因此,t(n)Θ(n2)t(n) \in \Theta(n^2)

基本渐近效率类

时间示例
1常数两数相加
logn\log n对数级二分搜索
nn线性查找nn个数中的最大值
nlognn \log nnn-log\log-nn或线性对数级许多分治算法,例如归并排序
n2n^2平方枚举所有元素对(通常是两个嵌套循环的算法),例如选择排序
n3n^3立方枚举所有三元组(通常是三个嵌套循环的算法)
2n2^n指数枚举nn个项的所有子集
n!n!阶乘生成nn个项的所有排列或顺序

性质

传递性:

  • 如果fO(g)f \in O(g)gO(h)g \in O(h),则fO(h)f \in O(h)
  • 如果fΩ(g)f \in \Omega(g)gΩ(h)g \in \Omega(h),则fΩ(h)f \in \Omega(h)
  • 如果fΘ(g)f \in \Theta(g)gΘ(h)g \in \Theta(h),则fΘ(h)f \in \Theta(h)

可加性:

  • 如果fO(h)f \in O(h)gO(h)g \in O(h),则f+gO(h)f + g \in O(h)
    • 如果fΩ(h)f \in \Omega(h)gΩ(h)g \in \Omega(h),则f+gΩ(h)f + g \in \Omega(h)
  • 如果fΘ(h)f \in \Theta(h)gΘ(h)g \in \Theta(h),则f+gΘ(h)f + g \in \Theta(h)

如果f1(n)O(g1(n))f_1(n) \in O(g_1(n))f2(n)O(g2(n))f_2(n) \in O(g_2(n)),则f1(n)+f2(n)O(max(g1(n),g2(n)))f_1(n) + f_2(n) \in O(\max(g_1(n), g_2(n)))

如果f1(n)Ω(g1(n))f_1(n) \in \Omega(g_1(n))f2(n)Ω(g2(n))f_2(n) \in \Omega(g_2(n)),则f1(n)+f2(n)Ω(max(g1(n),g2(n)))f_1(n) + f_2(n) \in \Omega(\max(g_1(n), g_2(n)))

如果f1(n)Θ(g1(n))f_1(n) \in \Theta(g_1(n))f2(n)Θ(g2(n))f_2(n) \in \Theta(g_2(n)),则f1(n)+f2(n)Θ(max(g1(n),g2(n)))f_1(n) + f_2(n) \in \Theta(\max(g_1(n), g_2(n)))

由两个依次执行的部分组成的算法的总体效率由具有更高增长阶数的部分决定(即其效率最低的部分)。

使用极限比较增长阶数

如果limnf(n)g(n)={0,f(n)O(g(n))c,f(n)Θ(g(n))f(n)O(g(n))f(n)Ω(g(n)),f(n)Ω(g(n))\lim_{n \to \infty} \frac{f(n)}{g(n)} = \begin{cases} 0, & \text{则} f(n) \in O(g(n)) \\ c, & \text{则} f(n) \in \Theta(g(n)) \text{且} f(n) \in O(g(n)) \text{且} f(n) \in \Omega(g(n)) \\ \infty, & \text{则} f(n) \in \Omega(g(n)) \end{cases}

例如,比较12n(n1)\frac{1}{2}n(n-1)n2n^2的增长阶数:

limn12n(n1)n2=12limnn2nn2=12limn(11n)=12\lim_{n \to \infty} \frac{\frac{1}{2}n(n-1)}{n^2} = \frac{1}{2} \lim_{n \to \infty} \frac{n^2-n}{n^2} = \frac{1}{2} \lim_{n \to \infty} (1 - \frac{1}{n}) = \frac{1}{2}

因此,12n(n1)Θ(n2)\frac{1}{2}n(n-1) \in \Theta(n^2)

总结

  • 时间效率:表示算法运行的速度
    • 输入规模的函数
    • 基本操作执行的次数
    • 最坏情况、平均情况、最佳情况
  • 渐近增长阶数
    • OOΩ\OmegaΘ\Theta表示法
  • 效率类别
    • 常数级(Constant)、对数级(Logarithmic)、线性级(Linear)、线性对数级(Linearithmic)、平方级(Quadratic)、立方级(Cubic)、指数级(Exponential)

文章标题:算法-02-算法分析与设计

文章作者:DWHITE

文章链接:https://dr9k69ai79.github.io/MyBlog/posts/schoolcoursesnotes/2024_04/dmt211_algorithm/02_算法分析与设计[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。