时间复杂度及常见案例

在数据结构中,使用时间复杂度来衡量程序运行时间的多少。每条语句执行的次数称为该语句的频度,整段代码的总执行次数则称为整段代码的频度。

  定义:在算法估算时,语句的执行次数T(n)是关于问题规模n的函数,从而分析T(n)随着n的变化的关系。算法的时间复杂度也称为算法的时间量度,记作T(n) = O(f(n)),它表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度,其中f(n)是问题规模n的某个函数。

  刚开始看上面的定义多少有些迷惑,但是多读几次结合上文的知识串起来后,你会其实并没有这么复杂,时间复杂度其实可以理解为随着问题规模n的增大,程序语句执行频度的增长率。

  在定义中我们使用到O()的方式来体现算法时间复杂度的记法,这种方式又称为大O记法。一般情况下,随着问题规模n的增大,T(n)即语句执行次数增长最慢的算法为最优算法,讲简单点,就是无论你输入规模如何变化,只要执行的语句次数增长最小,那这种算法就是最优的。

在推导的时候我们应该采用无限大的思想来简化大O表达式,具体如下:

用常数1代替运行时间中的所有加法的常数,如:某个算法的执行函数为f(n) = 10,则替换成大O阶方法的话则为:O(1),无论这个常数为10,还是100,还是1000都使用1替换,因为执行函数和问题规模n的大小无关,它是执行时间恒定的,像时间复杂度为O(1)的又被称作常数阶。

如果表达式有多项含有无限大变量的式子,只保留一个拥有指数最高的变量的式子。例如 2n²+2n 简化为 2n²;

如果最高阶项存在且系数不为1,则去除掉与这个项相乘的系数,例如 2n² 系数为 2,直接简化为 n² ;

常见的时间复杂度例子

  一、常数阶


int i,sum=0,n=100; // 执行1次
sum = (1 + n) * n / 2; // 执行1次
System.out.println("sum="+sum); // 执行1次
1
2
3

  这个算法就是上面我们举例到的高斯算法,程序的执行次数函数为f(n) = 3,根据大O阶方法的推导方式,则得到的时间复杂度为:O(1),而不是O(3),注意:因为执行函数并不会随着n的变化而变化,它是恒定的,像复杂度为O(1),又被称作常数阶。

  二、线性阶


int i,sum=0,n=100; // 执行1次
for(i=1;i<n;i++){
    sum = sum + i; // 执行n次
}
System.out.println("sum="+sum); // 执行1次
1
2
3
4
5

  根据上面的代码,我们可以发现执行次数函数为f(n) = n,根据大O阶方法的推导方式得到它的时间复杂度表示为:O(n)。 像这种线性阶,我们主要分析的是循环结构中的一个运行情况,从而得到它的时间复杂度。

  三、对数阶


int condition = 1;
while(condition < n){
    condition = condition * 2;
}
1
2
3
4

  根据上面的代码,我们会发现循环语句的条件会在每次condition乘以2后更加接近跳出条件,既满足多少个与2的乘积后将会退出循环,因此我们可以得到执行次数的函数为:f(n) => 2x = n ===> x = log2n,根据大O阶方法的推导方式得到它的时间复杂度表示O(logn)。

  四、平方阶


for(int i=o;i<n;i++){
    for(int j=o;j<n;i++){
        ...
    }
}
1
2
3
4
5

  根据代码分析,我们可以得到执行次数的函数为: f(n) = n2,根据大O阶方法的推导方式得到它的时间复杂度表示O(n2)。

例一:

T(n)=1                                 当n=1

T(n)=4T(n/2)+n                 当n>1

解:设n=2k ,则k=log2n, n/2k=1,由已知可以推出:

 T(n)=4T(n/2)+n=42T(n/22)+4Xn/2+n=42T(n/22)+3n=43T(n/23)+4n=...=

4kT(n/2k)+(5-1/2k-1X4)n=(2k)2T(1)+5n-8=n2T(1)+5n-8

所以时间复杂度为:O(n2)

主方法得出时间复杂度

例二:

  1. 分析以下递归方程的时间复杂度(t推荐使用主方法)。

T(n)=1                                 当n=1

T(n)=2T(n-1)+1              当n>1

解:

所以时间复杂度为:O(2n)

  1. 求以下代码的时间复杂度

void fun(int n)

{  int s=0,i,j,k;

   for (i=0;i<=n;i++)

         for (j=0;j<=i;j++)

              for (k=0;k<j;k++)

                    s++;

}

解:

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值