从【时间复杂度】到【函数的渐进上界】

函数渐进上界:一般意义上的时间复杂度

给定一个输入大小为 n 的函数:

void algorithm(int n) {
    int a = 1;  // +1
    a = a + 1;  // +1
    a = a * 2;  // +1
    // 循环 n 次
    for (int i = 0; i < n; i++) { // +1(每轮都执行 i ++)
        System.out.println(0);    // +1
    }
}

设算法的操作数量是一个关于输入数据大小 n 的函数,记为 T(n),则以上函数的操作数量为:

T(n) = 3+2n

T(n) 是一次函数,说明其运行时间的增长趋势是线性的,因此它的时间复杂度是线性阶。

我们将线性阶的时间复杂度记为O(n) ,这个数学符号称为大O记号(big-O notation),表示函数 T(n) 的 渐近上界(asymptotic upper bound)

时间复杂度分析本质上是计算“操作数量T(n) ”的渐近上界,它具有明确的数学定义。

如下图所示,计算渐近上界就是寻找一个函数 f(n) ,使得当 n 趋向于无穷大时, T(n) 和 f(n) 处于相同的增长级别,仅相差一个常数项 c 的倍数。

最差、最佳、平均时间复杂度

算法的时间效率往往不是固定的,而是与输入数据的分布有关

假设输入一个长度为 的数组 nums ,其中 nums 由从 至 的数字组成,每个数字只出现一次;但元素顺序是随机打乱的,任务目标是返回元素的索引。我们可以得出以下结论。

  • nums = [?, ?, ..., 1] ,即当末尾元素是 1 时,需要完整遍历数组,达到最差时间复杂度O(n\O
  • nums = [1, ?, ?, ...] ,即当首个元素为时,无论数组多长都不需要继续遍历,达到最佳时间复杂度 \Omega(1)

“最差时间复杂度”对应函数渐近上界,使用大O记号表示。

相应地,“最佳时间复杂度”对应函数渐近下界,用 \Omega 记号表示:

值得说明的是,我们在实际中很少使用最佳时间复杂度,因为通常只有在很小概率下才能达到,可能会带来一定的误导性。而最差时间复杂度更为实用,因为它给出了一个效率安全值,让我们可以放心地使用算法。

从上述示例可以看出,最差时间复杂度和最佳时间复杂度只出现于“特殊的数据分布”,这些情况的出现概率可能很小,并不能真实地反映算法运行效率。相比之下,平均时间复杂度可以体现算法在随机输入数据下的运行效率,用\Theta记号来表示。

对于部分算法,我们可以简单地推算出随机数据分布下的平均情况。比如上述示例,由于输入数组是被打乱的,因此元素 1 出现在任意索引的概率都是相等的,那么算法的平均循环次数就是数组长度的一半 ,平均时间复杂度为\Theta(n/2)=\Theta(n)。

但对于较为复杂的算法,计算平均时间复杂度往往比较困难,因为很难分析出在数据分布下的整体数学期望。在这种情况下,我们通常使用最差时间复杂度作为算法效率的评判标准。

总结:

  • 最差时间复杂度用O表示(读作:big O)
  • 最佳时间复杂度用\Omega表示
  • 平均时间复杂度用\Theta表示

声明:本文内容来自于开源项目 Hello 算法,更多资源请移步学习。

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder.Ren

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值