大话数据结构 (学习笔记)第二章 算法(下)

第二章 算法(下)

2.9算法的时间复杂度

判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注最高阶项的阶数。某个算法,随着n的增大,它会越来越优于另一个算法,或者越来越差于另一算法。

2.9.1 算法时间复杂度定义

算法的时间复杂度,也就是算法的时间量度,记作T(n) = O(f(n))。它表示随着问题规模n的增大,算法执行时间的增长率和n的某个函数f(n)的增长率相同。

2.9.2 推导大O阶方法

  1. 用常数1取代运行时间中的所有加法常数。
  2. 在修改后的运行次数函数中,只保留最高阶项。
  3. 如果最高阶项存在且不是1,则去除与这个项相乘的常数。得到的结果就是大O阶。

 2.9.3 常数阶

以求和代码为例:

这个代码的运行次数函数 f(n) = 3。根据推导大O阶方法,用1取代3,无最高阶项,因此该算法的时间复杂度为O(1)。假设该算法中计算sum这一步有10句,即:

事实上,无论n为多少,上述两段代码就是3次和12次执行的差异。这种与问题规模n大小无关,执行时间恒定的算法,称之为具有O(1)的时间复杂度,又叫常数阶。不论这个常数是多少,我们都记作O(1),而不能是O(3)、O(12)等其他任何数字!

对于分支结构,无论真、假,执行次数都是恒定的,不会随n的变化而变化,所以单纯的分支结构(不包含在循环结构中),其时间复杂度也是O(1)。

2.9.4 线性阶

我们要分析算法的复杂度,关键就是分析循环结构的运行情况。

这段代码的循环的时间复杂度为O(n)。

2.9.5 对数阶

这段代码每循环一次 i * 2 之后 i 就距离 a 更近了一点,循环 x 次后直到 i 大于或者等于 a 后,循环结束。所以有 2^x = a,x = log2^n。所以这个代码的时间复杂度为O(logn)。

2.9.6 平方阶

这是一个循环嵌套,外层循环执行了 m 次,内层循环执行了 n 次,因此,时间复杂度即为O(m*n)

这个循环 i 从0开始循环,j 从 i 开始循环。当i = 0时,内循环执行了n次,i= 1时,内循环执行n-1次,.......当i= n-1 时,内循环执行1次。所以总的执行次数为n + (n-1) + (n-2) + ... +1 = n(n+1)/2 = n^2/2 +n/2。根据推导大O阶的方法,这段代码的时间复杂度为O(n^2)。

看到这,我们发现,确实理解大O阶推导并不难,难的是对数列的一些相关运算,这更多考验数学知识和能力。

下面是一个关于方法调用的时间复杂度的计算。

function()函数的时间复杂度为O(1),所以整体的时间复杂度为O(n)。

假如function()是这样

这就和上文嵌套函数是一样的,只不过把内循环放到了函数里,所以最终的时间复杂度为O(n^2)。

下面这段相对复杂的语句:

它的执行次数 1 + n + n^2 + n(n+1)/2 = (3/2)*n^2 + (3/2)*n + 1,根据大O阶的方法,最终代码的时间复杂度为O(n^2)。

2.10 常见的时间复杂度

常见的时间复杂度所耗费的时间从小到大依次是:

O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O( n!) < O(n^n)

一般在没有特殊说明的情况下,时间复杂度都指最坏时间复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值