zoukankan      html  css  js  c++  java
  • 浅谈时间复杂度

    1.时间复杂度是什么?

    有人说,这还不简单,不就是在给定输入规模时,求所执行的基本操作数量吗?如下:

    int n=10;
    int count=0;
    for(int i=0;i<n;i++){//循环次数
         for(int j=0;j<n;j++){//执行深度
             count++;
       }
     }
    //count=100

    看到这个,时间复杂度无疑是O(n^2),再看看下面的

    int n=10;
    int count=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<i;j++){
           count++;
       }
     }
    //count=45

    看到这个,时间复杂度也是O(n^2),这里要出来一个概念,次数和时间复杂度的区别:

    第一个程序运行的次数是100(n*n=n^2),第二个程序运行的次数是45(0+1+2+3+4+...........+n-1=n*(n-1)/2),时间复杂度一样的原因是:当n趋于无穷大时可忽略常数,-1,/2可忽略。但是时间复杂度是在次数的基础上计算出来的。而次数就是循环次数*执行深度。

    2.什么是大O?

    比如我说一个变量x,并且有x在[a,b]这个区间,就表示了上界是a下界是b,对于变量x的取值范围来说,最大不超过b,最小不小于a。在算法中,上界就是对于一种资源的限制最大不大于的值,下界就是对于这种资源的限制最小不小于的值。这里的资源可以是时间、空间、带宽……

    所以当n趋于无穷时,O(2n^2)=O(n^2),O(n*(n-1)/2)=O(n^2),O(5n)=O(n),O(5)=O(1)。

    总结来说,大O表示算法执行的最低上界。

    3.为什么要进行计算时间复杂度?

    我们先来看张图:

    如果老板给你一个任务,让你对公司的账单从大到小进行排序,你可能会直接使用数据库自带的语句order by,的确,这是个好办法。如果你细致了解数据库,数据库的底层使用了B+树为数据建立了索引,时间复杂度明显降低。换个简单例子,如果老板让你把一堆数字进行排序,你可能最先想到选择排序,每次选择最小的数。老板说,这个太耗时了,你又会想到快速排序,选择一个基准数进行比较。老板又说,我给你的这些数基本有序,你又会想到插入排序,因为插入排序在基本有序的时候,算法复杂度接近O(n)。老板说,我还想快点,你想到了快速排序与插入排序的结合,等到快速排序排到很有序的时候,插入排序就有作用了。老板又说,我想在这些排序好的数字找到中间的数,这时候你可能想到,我直接数组[(0+n)/2]输出就行了,对的,因为数组本身就是一种很快的数据结构,相当于给每个数建立了索引,就可以直接取出数来,时间复杂度复杂度O(1)。

    梳理一下:时间复杂度分别向O(n^2),O(nlogn),O(n),O(nlogn)+O(n),O(1)演变

    复杂度 标记符号 描述
    常量(Constant)

     O(1) 

    操作的数量为常数,与输入的数据的规模无关。

    n = 1,000,000 -> 1-2 operations 

    对数(Logarithmic)

     O(log2 n) 

    操作的数量与输入数据的规模 n 的比例是 log2 (n)。

    n = 1,000,000 -> 30 operations

    线性(Linear)  O(n)

    操作的数量与输入数据的规模 n 成正比。

    n = 10,000 -> 10000 operations

    平方(Quadratic)  O(n2)

    操作的数量与输入数据的规模 n 的比例为二次平方。

    n = 500 -> 250,000 operations

    立方(Cubic)  O(n3)

    操作的数量与输入数据的规模 n 的比例为三次方。

    n = 200 -> 8,000,000 operations

    指数(Exponential)

     O(2n)

     O(kn)

     O(n!)

    指数级的操作,快速的增长。

    n = 20 -> 1048576 operations

    为什么要这样演变呢?

    时间复杂度的演变,就是为了更快更好的解决问题,使其效率越来越高。

    另外贴出问题规模与执行时间之间的关系图:

    复杂度 10 20 50 100 1000 10000 100000
    O(1)

    <1s

    <1s

    <1s

    <1s

    <1s

    <1s

    <1s

    O(log2(n))

    <1s

    <1s

    <1s

    <1s

    <1s

    <1s

    <1s

    O(n)

    <1s

    <1s

    <1s

    <1s

    <1s

    <1s

    <1s

    O(n*log2(n))

    <1s

    <1s

    <1s

    <1s

    <1s

    <1s

    <1s

    O(n2)

    <1s

    <1s

    <1s

    <1s

    <1s

    2s

    3-4 min

    O(n3)

    <1s

    <1s

    <1s

    <1s

    20s

     5 hours 

     231 days 

    O(2n)

    <1s

    <1s

     260 days 

     hangs 

     hangs 

    hangs

    hangs

    O(n!)

    <1s

     hangs 

    hangs

     hangs 

    hangs

    hangs

    hangs

    O(nn)

     3-4 min 

    hangs

    hangs

     hangs 

    hangs

    hangs

    hangs

    上面关于排序的优化的文章我在前面已经做出Java代码的演示,地址:从优化的角度谈谈排序

    谢谢大家的阅读,博客不易,转载请注明地址。

  • 相关阅读:
    关于zabbix 的lld的web界面的配置
    fastdfs+nginx的安装部署
    mybatis 模糊查询写法
    mybatis-generator:generate failed: Exception getting JDBC Driver: com.mysql.jdbc.Driver
    mybatis判断不为空,不为null等
    mybatis错误:Parameter 'companyName' not found. Available parameters are [arg3, arg2, arg1, arg0,..]
    oracle数据库 ORA-01810: 格式代码出现两次
    Shell学习(一)
    本地计算机上的OracleOraDb11g_home1TNSListener服务启动后停止
    net share c$=c: 发生系统错误
  • 原文地址:https://www.cnblogs.com/huhu1203/p/8045263.html
Copyright © 2011-2022 走看看