算法效率分析之时间复杂度O

一、什么是时间复杂度?

时间复杂度是一个函数,它定性描述该算法的运行时间

它可以方便开发者估算出程序的运行时间

请回忆一下自己刚开始刷题的时候,我自己刚开始刷题的时候,经常会使用暴力法来求解一些问题(所谓暴力法,就是直接将问题的所有可能情况列举出来,然后留下符合题目要求的情况)

虽然直接暴力出来的感觉很棒:)但是当题目的数据范围较大的时候,就会引出两个问题:1)所有的情况无法全部列举出来,或者说是比较难列举出来所有情况;2)即使考虑到了所有情况,但是遍历所有情况的时间已经超出题目限制了。

所以,虽然能否解出问题是最重要的,但我们也需要考虑算法的时间、空间等其他效益是否合理。

那么,我们该如何估计程序运行时间呢,通常,我们会估计算法的操作单元数量,来代表程序消耗的时间, 这里我们就默认CPU的每个单元运行消耗的时间都是相同的,即认为每一个单元运行消耗时间为1。

我们假设算法的问题规模为n,那么操作单元数量就可以用函数关系F(n)来表示

随着数据规模n的增大,算法执行时间的增长率和F(n)的增长率是相同的,这称作为算法的渐近时间复杂度,简称时间复杂度,记为 O(f(n))

二、什么是大O?

由于在算法导论一书(非常好的一本算法学习书籍,初学算法的我自己感觉是非常受用的)中,对于算法复杂度给出了比较清晰的解释,所以我在这里直接引用书中的原文来加以解释

即:“大O用来表示上界的,当用它作为算法的最坏情况运行时间的上界,就是对任意数据输入(数据规模是时间复杂度的自变量)程序运行时间的上界。”

在我们自己描述的时候,一般也是考虑最坏情况,但是当我们学习到其他算法的时候,针对一些极端情况,算法的表现会不一样,所以这个时候,大O往往是指的一般情况

三、如何描述(计算)时间复杂度?

分析算法的执行时间

求出算法所有原操作的执行次数(也称为频度),它是问题规模n的函数,用 T(n) 表示。

算法执行大致时间 = 原操作所需的时间 * T(n)

所以算法的执行时间与 T(n) 成正比 为此用 T(n) 表示算法的执行时间

频度的计算

先来看一段代码

for (i = 0; i < n; i++) {                                      //语句 1   频度为 n+1
    for (j = 0; j < n; j++) {                              //语句 2   频度为 n*(n+1)
        c[i][j] = 0;                                   //语句 3   频度为 n*n 
            for (k = 0; k < n; k++)                        //语句 4   频度为 n*n*(n+1)
                c[i][j] = c[i][j] + a[i][k] * b[k][j]; //语句 5   频度为 n*n*n       
    }
}

来解释一下,每个语句的频度

语句1:

不看内循环,单独看语句 1 ,当i范围在 [0,n-1] 时,它执行了n次,i=n时还执行了一次(判断后跳出循环),所以是n+1次。

语句2:

一样,不看 内循环 和 外循环,单独看语句2,语句2执行了n+1次 ,再看外循环,也就是语句1 循环了 n 次(频度是n+1,但是 循环次数并不是n+1次) 所以语句2 的频度为 n*(n+1)

语句3:

不看外循环,执行一次,再看外循环,执行n*n次 故 频度为n²

语句4和语句5的频度就不做解释了

得出这个段代码的 频数之和

T(n) = 2n³ + 3n² + 2n + 1

那么此时算法的大O是什么呢?我们知道大O表示运行时间的上界。

所以当数据规模增大,也就是n趋于无穷大时,n的三次方明显会比其他项的增长速度更快,所以我们省略掉除最高项的其他次项。

接着,对于一个无穷大的数而言,它之前的系数也是可以忽略的了。因为无穷大乘上非零常数,也仍然是无穷大。

所以最后化简完表达式,就是n的三次方,所以算法的时间复杂度就是O(n³)

总结,运行时间表达式的化简一般可遵循以下步骤(参考自《代码随想录》):
1)去掉运行时间中的常数项

因为常数项并不会因为n的增大而增加计算机的操作次数

2)去掉常数项系数

因为大O就是数据量级突破一个点且数据量级非常大的情况下所表现出的时间复杂度,这个数据量也就是常数项系数已经不起决定性作用的数据量。但是也要注意大常数,如果这个常数非常大,例如10^7 ,10^9 ,那么常数项就是需要考虑的因素了。

3)保留保留最高次项


时间复杂度都是省略常数项系数的,是因为一般情况下都是默认数据规模足够的大,基于这样的事实,给出的算法时间复杂的的一个排行如下所示:

O(1)常数阶 < O(logn)对数阶 < O(n)线性阶 < O(n^2)平方阶 < O(n^3)立方阶 < O(2^n)指数阶

当算法的时间复杂度越小时,说明该算法的时间性能表现越好。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

PL_涵

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

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

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

打赏作者

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

抵扣说明:

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

余额充值