• 时间复杂度计算题


    时间复杂度

    一、常见的时间复杂度

    1. 常数阶

    这种与问题规模的大小无关(n的多少),执行时间恒定的算法,我们称之为具有O(1)的时间复杂度,又叫常数阶。

    1. int sum = 0, n = 100; /*执行一次*/
    2. sum = (1 + n) * n / 2; /*执行一次*/
    3. printf("%d",sum); /*执行一次*/

    2. 线性阶

    下面这段代码,它的循环的时间复杂度为O(n), 因为循环体中的代码须要执行n次。

    1. int i;
    2. for(i = 0; i < n; i++){
    3. /*时间复杂度为O(1)的程序步骤序列*/
    4. }

    3. 对数阶

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

    1. int count = 1;
    2. while (count < n){
    3. count = count * 2;
    4. /*时间复杂度为O(1)的程序步骤序列*/
    5. }

    4. 平方阶

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

    1. int i, j;
    2. for(i = 0; i < n; i++){
    3. for(j = 0; j < n; j++){
    4. /*时间复杂度为O(1)的程序步骤序列*/
    5. }

    循环的时间复杂度等于循环体的复杂度乘以该循环运行的次数。

    1. int i, j;
    2. for(i = 0; i < n; i++){
    3. for(j = i; j < n; j++){ /*注意j = i而不是0*/
    4. /*时间复杂度为O(1)的程序步骤序列*/
    5. }
    6. }

    5、对于顺序执行的语句或者算法,总的时间复杂度等于其中最大的时间复杂度

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

     

    二、时间复杂度的计算过程中的忽略原则

    • 加法常数项可以忽略
    • 除去最高阶项,其它次项可以忽略
    • 与最高次项相乘的常数可以忽略

    三、时间复杂度大O记法

    T(n)=O(f(n))

    该公式中的O表示代码的执行总时间T(n)和其执行总次数f(n)成正比。这种表示法,称之为大O记法。大O记法T(n)=O(f(n)),表示随着代码执行的次数增长(减少),算法执行时间的增长率和f(n)的增长率相同,表示的是算法的渐近时间复杂度,简称时间复杂度。
    我们通过下面这个例子,来看一下如何使用该公式;
     

    1. int sum = 0; //执行一次
    2. for (int i = 0; i < n; i++) {//执行n次
    3. b = 2 * i;//执行n次
    4. for (int j = 0; j < n; j++) {//执行n*n次
    5. sum += i + j;//执行n*n次
    6. }
    7. }

    分析得出上面代码执行的总次数f(n) = 1 + n + n + nn + nn = 2n²+2n+1 。
    因此可以推出时间复杂度T(n) = O(2n²+2n+1 )。当n趋近于无穷大时,T(n)的增长主要与n²有关系,所以我们通常也将上述代码的时间复杂度写为T(n) = O(n²);

    四、时间复杂度分析

    时间复杂度的分析有一个基本的法则:四则运算法则

    1、加法法则

    如果算法的代码是平行增加的,则只需加上所对应的时间复杂度。
    接下来通过以下例子来讲解加法法则
    下面代码执行的总次数为:f(n) = 1 + n + n;所以时间复杂度为T1(n) = O(2*n + 1)。当n趋近于无穷大时,T1(n) = O(n);

    1. int sum = 0;//只执行一次
    2. for (int i = 0; i < n; i++) {//执行n次
    3.     count++;//执行n次
    4. }


    在上述的代码基础上平行增加部分代码,增加后如下所示:
    增加前时间复杂度为:T1(n) = O(2n + 1),增加部分的代码执行次数f(n) = 1 + n + n + n;所以增加的代码时间复杂度T2(n) = O(3n + 1);因为代码是平行增加的所以增加后的时间复杂度T(n) = T1(n) + T2(n) = O(5*n + 2)。当n趋近于无穷大时,T(n) = O(n);

    1. int count = 0;//只执行一次
    2. int sum = 0;//只执行一次
    3. for (int i = 0; i < n; i++) {//执行n次
    4. count++;//执行n次
    5. }
    6. for (int j = 0; j < n; j++) {//执行n次
    7. sum += j;//执行n次
    8. sum += 2*j;//执行n次
    9. }


    2、乘法法则

    如果算法的代码增加的是循环内的嵌套或者函数的嵌套,那么就需要乘上相应的时间复杂度。
    如果不能理解这句话,别着急,接着往下看,下面的例子会帮助你理解
    接下来通过以下例子来讲解乘法法则
    在上面已经分析过,下面的代码时间复杂度T1(n) = O(2*n + 1),也可以写成T1(n) = O(n);

    1. int sum = 0;//只执行一次
    2. for (int i = 0; i < n; i++) {//执行n次
    3. count++;//执行n次
    4. }


    在上述的基础上我们增加部分代码,增加后如下所示;
    下面增加了一个内层循环,增加的部分如果单独看,则执行了m次,但是由于是嵌套增加的,所以当外层循坏执行一次,内层循环就会执行m次。所以当外层循环执行n次时,内层循环就会执行n*m次,所以下面代码执行的总次数f(n) = 1 + n + n + nm + nm。由时间复杂度O的定义可计算出下面代码的时间复杂度T(n) = O(2nm + 2n + 1)。当n和m趋近于无穷大时,可以认为n=m,则可以写为T(n) = O(2n² + 2n + 1)。由于n和m趋近于无穷大,所以T(n)的增长主要受n²的增长影响,所以可以写为T(n) = O(n²)
     

    1. int sum = 0;//只执行一次
    2. for (int i = 0; i < n; i++) {//执行n次
    3. count++;//执行n次
    4. for (int j = 0; j < m; j++) {//执行n*m次
    5. count++;//执行n*m次
    6. }
    7. }

    3、除法法则和减法法则

    减法和除法我相信大家通过上面的讲述可以自己推导出来,我就不多写了。我把主要的思想写在下面,供大家参考

    减法法则,如果是去掉算法中平行的代码,就需要减掉相应的时间复杂度。
    除法法则,如果是去掉嵌套内的循环或函数,就需要除去相应的时间复杂度。


    四、图形分析

    对于上述这些常见时间复杂度,它们的执行次数T(n)和问题规模n的关系如下图:

  • 相关阅读:
    echarts的双向柱形图的legend图例不显示的原因是,sereies里的数据,没有写name属性,必须要写,图例才会出现
    【Java】初识IO流【附导航】
    SSM整合(二)
    输出有价值的性能报告
    细数实现全景图VR的几种方式(panorama/cubemap/eac)
    老杨说运维|今年这个会议非比寻常
    GamingTcUI.dll丢失修复,最全面的GamingTcUI.dll修复指南
    基于B2B平台的医疗病历交互系统
    java获取中文拼音
    数据结构——空间复杂度
  • 原文地址:https://blog.csdn.net/zhangt766/article/details/126611255