为了账号安全,请及时绑定邮箱和手机立即绑定

简单程序的时间复杂度分析

标签:
Java

一、算法的概念
算法中基本操作的执行次数一般是与问题的规模有关的。对于节点个数为n的数据处理问题,用T(n)表示算法基本操作的执行次数。为评价算法的时间复杂度与空间复杂度,我们引入记号为“O”的数学符号。设T(n)和f(n)是定义在正整数集合上的两个函数,如果存在正常数C和No,使得当n>=No时,都有0<=T(n)<=C*f(n),则记T(n)=0(f(n))。在评价算法的时间复杂度时,不考虑两个算法执行次数之间的细小区别,而只关心算法的本质区别。
常见算法时间复杂度排序为:
**Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
图片描述
算法时间复杂度的最小、最大和平均值:

  1. 算法在最好的情况下的时间复杂度是指算法计算量的最小值。
  2. 算法在最坏的情况下的时间复杂度是指算法计算量的最大值。
  3. 算法在平均情况下的时间复杂度是指算法在所可能的情况下的计算量经过加权计算出的平均值。
    csdn找到的算法的描述

二、常用程序的简单的时间复杂度分析
**首先我们将每次执行一行程序的时间复杂度记为O(1)。
时间复杂度分析的基本策略是:从内向外分析,从最深层开始分析。如果遇到函数调用,要深入函数进行分析。

1、对于一个循环,假设循环体的时间复杂度为 O(n),循环次数为 m,则这个
循环的时间复杂度为 O(n×m)。

void aFunc(int n) {
    for(int i = 0; i < n; i++) {         // 循环次数为 n
        printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
    }
}

所以上述程序的时间复杂度为O(n×1),为O(n)。由此延伸,多重循环的时间复杂度可以内外层循环相乘获得

void aFunc(int n) {
    for(int i = 0; i < n; i++) {         // 循环次数为 n
          for(int i = 0; i < n; i++) {         // 循环次数为 n
            printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
    }
    }
}

所以上述程序的时间复杂度为O(n × n × 1)=O(n^2)。


2.对于顺序执行的程序语句,时间复杂度可用叠加计算

void aFunc(int n) {
    for(int i = 0; i < n; i++) {         // 循环次数为 n
          for(int i = 0; i < n; i++) {         // 循环次数为 n
            printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
           }
    }
    for(int i = 0; i < n; i++) {         // 循环次数为 n
            printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
    }
}

所以时间复杂度的计算为O(n^2)+O(n),由于只考虑量级的关系,所以该代码块的时间复杂度为O(n^2)。


3.对于条件判断语句,总的时间复杂度等于其中 时间复杂度最大的路径 的时间复杂度。

void aFunc(int n) {
    if (n >= 0) {
        // 第一条路径时间复杂度为 O(n^2)
        for(int i = 0; i < n; i++) {         // 循环次数为 n
          for(int i = 0; i < n; i++) {         // 循环次数为 n
            printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
           }
       }
    } else {
        // 第二条路径时间复杂度为 O(n)
         for(int i = 0; i < n; i++) {         // 循环次数为 n
            printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
       }
    }
}

此时的时间复杂度为O(n^2)。


练习1

void aFunc(int n) {
    for (int i = 2; i < n; i++) {        //条件控制  i<n
        i *= 2;            //    i=i*2
        printf("%i\n", i);
    }
}

需要满足i*2<n,所以循环次数为log(2)(n),所以时间复杂度为O(log(2)(n))即为O(log n).


练习

long aFunc(int n) {
    if (n <= 1) {
        return 1;
    } else {
        return aFunc(n - 1) + aFunc(n - 2);
    }
}

显然运行次数,T(0) = T(1) = 1,同时 T(n) = T(n - 1) + T(n - 2) + 1,这里的 1 是其中的加法算一次执行。
显然 T(n) = T(n - 1) + T(n - 2) 是一个斐波那契数列,通过归纳证明法可以证明,当 n >= 1 时 T(n) < (5/3)^n,同时当 n > 4 时 T(n) >= (3/2)^n。
所以该方法的时间复杂度可以表示为 O((5/3)^n),简化后为 O(2^n)。

练习部分的程序分析来源于简书作者raymondCaptain
链接:https://www.jianshu.com/p/f4cca5ce055a

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
17
获赞与收藏
174

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消