数据结构(二)——时间复杂度+例子分析(相当清晰)

上一篇博客写到,评价算法优劣使用时间和空间复杂度去描述的,这一篇博客就写一下时间复杂度的有关内容


时间复杂度定义


在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。时间复杂度记作:T(n)=O(f(n)).它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称时间复杂度。
 

发现官方定义极其高大上,换成大白话
算法主要是由输入输出语句,三大结构语句等组成的,大部分会有循环(局部性原理),随着某一个自变量(比如i)的值从最小值取到n,算法所有语句总的执行次数随着n的增大,会呈现一个关于n的函数关系即f(n),经过大O表示法处理,得到T(n)=O(f(n));

 

大O表示法

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

大O表示法的由来
 下面举出三个算法n与f(n)的关系

数据结构(二)——时间复杂度+例子分析(相当清晰)_第1张图片

可以从结果看出,在判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,更应该关注最高阶项的阶数


举例:


数据结构(二)——时间复杂度+例子分析(相当清晰)_第2张图片

这四种情况基本涵盖了算法(程序)的时间复杂度分析的80%,二八定律嘛,咱们一个个来看
 

常数阶


看下面的例子

求出这个算法的时间复杂度

答案是O(1)

解释:
f(n)是指算法中所有语句的执行次数,便是f(n)=3,时间复杂度为O(f(n)),所以应该为O(3),可是答案为什么是O(1)呢?
这里就是大O表示的法第一条:用常数1取代运行时间中的所有常数项。那么问题又来了,为什么第一条这么定义呢?
咱们回归到定义:随着某一个自变量(比如i)的值从最小值取到n,算法所有语句总的执行次数随着n的增大,会呈现一个关于n的函数关系即f(n),这里某一个自变量(比如i)的值从最小值取到n是指n的规模,与n的具体大小无关
 

线性阶(循环结构)

int i
for(i=0;i

此时时间复杂度便为O(n);

对数阶

看下列代码
数据结构(二)——时间复杂度+例子分析(相当清晰)_第3张图片

时间复杂度答案为O(logn)

解释:
再回归之前的定义,这里某一个自变量(比如i)的值从最小值取到n是指n的规模,这里是指遍历,从最小值依次取到n,而这里由于count乘以2之后,就距离n更近了一些,有跳跃性,也就是说,有多少个2相乘后大于n,则会退出循环。
因为f(n)为总的执行次数,而这里的执行次数便为x,所以O(f(n))=O(x)=O(logn),到这里就有童鞋问了,

为什么时间复杂度不是以2为底的对数?
答案:因为在对数运算中有一个换底公式

数据结构(二)——时间复杂度+例子分析(相当清晰)_第4张图片

log以c为底的2的对数,显然是一个常数,根据大O表示法的第三条:如果最高阶项存在且不是1,则去除与这个项相乘的系数,因此时间复杂度就变为O(以c为底的n的对数),所以显然大O表示法对数阶跟底数没有关系
 

平方阶

int i
for(i=0;i

这里便是循环嵌套,两个循环之间没有什么关系,所以时间复杂度便为O(n2);

 

总结:

至此时间复杂度大致的东西就总结完成了,有什么不妥的地方,还望大家斧正!

你可能感兴趣的:(#,数据结构与算法,#,自考之路,数据结构,时间复杂度)