《大话数据结构》

推导大O阶方法


那么如何分析一个算法的时间复杂度呢?即如何推导大O阶呢?我们给出了下面的推导方法,基本上,这也就是总结前面我们举的例子。
 

仿佛像是得到了游戏攻略一样,我们好像已经得到了一个推到算法时间复杂度的万能公式。可事实上,分析一个算法的时间复杂度,没有这么简单,我们还需要多看几个例子


常数阶


首先顺序结构的时间复杂度。下面这个算法,也就是刚才的第二种算法,为什么时间复杂度不是O(3)而是O(1)。
 
这个算法的运行次数函数是f(n) = 3.根据我们推倒大O阶的方法,第一步就是把常数项3改为1.在保留最高阶项时发现,它根本没有最高阶项。所以这个算法的时间复杂度为O(1)。
另外,我们试想一下,如果这个算法当中的语句sum=(1+n)* n/2有10句,即:
 
事实上无论n为多少,上面的两端代码就是三次和十二次执行的差异。这种与问题的大小无关,执行时间恒定的算法,我们称之为具有O(1)的时间复杂度,又叫常数阶。
注意:不管这个常数是多少,我们都记作O(1),而不能是O(3)、O(12)等其他任何数字,这是初学者常常犯的错误。对于分支结构而言,无论是真还是假,执行的次数都是恒定的,不会随着n的变大而发生改变,所以单纯的分支结构,其时间复杂度也是O(1)


线性阶


线性阶的巡护结构会复杂很多,要确定某个算法的阶次,我们常常需要确定某个特定语句或某个语句集运行的次数。因此,我们要分析算法的复杂度,关键就是要分析巡护结构的运行次数。
下面这段代码,它的循环的时间复杂度为O(n),因为循环体中的代码必须要执行n次

 

对数阶



下面这段代码,时间复杂度又是多少呢

由于每次count乘以2之后,就距离n更近了一分。也就是说,有多少个2相乘后大于n,则会退出循环。由2x的平方=n得到x=log2n。所以这个循环的时间复杂度为0(logn)


平方阶


下面例子是一个循环嵌套,他的内循环刚才我们已经分析过,时间复杂度为O(n)


而对于外层的循环,不过是内部这个时间复杂度为O(n)的语句,再循环n次。所以这段代码的时间复杂度为O(n的二次方)。如果外循环的循环次数改为了m,时间复杂度就变为O(m×n)


所以我们可以总结得出,循环的时间复杂度等于循环体的复杂度乘以该循环运行的次数。那么下面这个循环嵌套,他的时间复杂度是多少呢


 由于当i = 0时,内循环执行了n次,当i = 1时,执行了n-1次,……当i = n-1时,执行了一次,所以总
的次数为 用我们推导大O阶的方法,第一条没有加法常数不予考虑;第二条,只保留最高阶项,因此保留 ;第三条,去除这个项相乘的常数,也就是取出1/2,最终这段代码的时间复杂度为O(n的二次方)。
从这个例子,我们也可以得到一个经验,其实理解大O推导不算难,难的是对数列的一些相关运算,着更多的是考察你的数学知识的能力,所以想考研的朋友,要想在求算法时间复杂度这里不失分,可能需要强化你的数学,特别是数列方面的知识和解题能力。
我们继续看例子,对于方法调用的时间复杂度又如何分析。
int i,j;
for (i = 0; i < n; i++)
{
function(i);
}
上面这段代码调用一个函数function。
void function(int count)

print(count);

函数提示打印这个函数。其实这很好理解,function函数的时间复杂度是O(1)。所以整体的时间复杂度为O(n)。假如function是下面这样的:
void function(int count)

int j;
for(j = count; j < n; j++)

/*时间复杂度为O(1)的程序步骤序列 */


事实上这和刚才举得例子是一样的,只不过把嵌套内循环放到了函数中,所以最终的时间复杂度为O(n²)。
下面这段相对复杂的语句:
 n++; /* 执行次数为1 */
 function(n); /* 执行次数为n */
 int i,j;
 for(i = 0; i < n; i++) /* 执行次数为n² */


 {
function(i);
 }
 for(i = 0; i < n; i++) /* 执行次数为n(n + 1)/2 */
 {
for(i = 0 ; i < n ; i++)
 
/*时间复杂度为O(1)的程序步骤序列*/

 }
它的执行次数f(n)= l + n + n²+ ,根据推导大 O 阶的方法,最终这段代码的时间复杂度也是 O(n²)。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值