• 算法时间复杂度


    一、什么是算法的时间复杂度

    (一)引出算法

    什么是算法?加入有下面一道题:

    如果 a+b+c=1000,且 a^2+b^2=c^2(a,b,c 为自然数),如何求出所有a、b、c可能的组合?

     刚开始的想法可能就是将a、b、c可能的值都列出来然后进行组合:

    • a、b、c的可能取值范围是[0,1000]
    • 然后根据枚举进行条件组合
    import time
    
    
    def outter(func):
        def innder(*args, **kwargs):
            start = time.time()
            func()
            end = time.time()
            print('运行时间:%s' % (end - start))
    
        return innder
    
    
    @outter
    def find():
        for i in range(0, 1001):
            for j in range(0, 1001):
                for k in range(0, 1001):
                    if i + j + k == 1000 and i ** 2 + j ** 2 == k ** 2:
                        print(i, j, k)
    
    
    find()

    输出的结果如下:

    0 500 500
    200 375 425
    375 200 425
    500 0 500
    运行时间:182.12541675567627

    显然,这样会耗费非常多的时间,如果换一种思路,当a、b确认后c是不是也就可以通过1000-a-b进行确认了呢?进行如下优化:

    import time
    
    
    def outter(func):
        def innder(*args, **kwargs):
            start = time.time()
            func()
            end = time.time()
            print('运行时间:%s' % (end - start))
    
        return innder
    
    
    @outter
    def find():
        for i in range(0, 1001):
            for j in range(0, 1001):
                k = 1000 - i - j
                if i ** 2 + j ** 2 == k ** 2:
                    print(i, j, k)

    此时的输出为:

    0 500 500
    200 375 425
    375 200 425
    500 0 500
    运行时间:1.328075885772705

    可以看到运行的时间从182.12541675567627s减少到1.328075885772705s,进行很大空间的优化。

    我们通过不同的方法和思想,达到不一样的效果,这就是一种算法,算法是独立存在的一种解决问题的方法和思想。

    (二)时间复杂度

    1、什么是时间复杂度

      上述的两种算法,显然第二种更优,但是你是如何衡量算法的效率呢?仅仅通过时间来进行判断吗?如果仅仅通过时间来判断显然是不合适的,因为如果第二种算法跑在一个硬件设备配置很低的机器,可能耗费的时间更长。

      虽然从时间上不能衡量,但是一个算法有多少基本操作是确定的,多少个基本操作就代表会花费多少时间单位,这样就可以忽视机器环境的影响。对于算法效率的衡量可以使用“大O记法”:

      对于单调的整数函数f,如果存在一个整数函数g和实常数c>0,使得对于充分大的n总有f(n)<=c*g(n),就说函数g是f的一个渐近函数(忽略常数),记为f(n)=O(g(n))。也就是说,在趋向无穷的极限意义下,函数f的增长速度受到函数g的约束,亦即函数f与函数g的特征相似。

    对于时间复杂度就是:

      假设存在函数g,使得算法A处理规模为n的问题示例所用时间为T(n)=O(g(n)),则称O(g(n))为算法A的渐近时间复杂度,简称时间复杂度,记为T(n)

    2、如何计算时间复杂度

    • 基本操作,即只有常数项,认为其时间复杂度为O(1)
    • 顺序结构,时间复杂度按加法进行计算
    • 循环结构,时间复杂度按乘法进行计算
    • 分支结构,时间复杂度取最大值

    判断一个算法的效率时,往往只需要关注操作数量的最高次项,其它次要项和常数项可以忽略;在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度

    比如上面算法1抽象的时间复杂度:

    T(n) = n * n * n * max(1,0) = n^3*1 = n^3 = O(n^3)

    对于上面算法2抽象的时间复杂度:

    T(n) = n*n*(1+max(1,0)) = n^2 * (1+1) = 2*n^2 = n^2 =O(n^2)

    由此可见第2中算法更优。

    3、常见时间复杂度

    次数函数 阶数 术语
    3 O(1) 常数阶
    2n+3 O(n) 线性阶
    2n2+3n+1 O(n2) 平方阶
    5log2n+10
    O(logn) 对数阶
    3n+3nlog2n+20 O(nlogn) nlogn阶
    5n3+2n2+3n+4 O(n3) 立方阶
    2n O(2n) 指数阶

    上述时间复杂度所消耗的时间从小到大:

    O(1) < O(logn) < O(n) < O(nlogn) < O(n
    2
    ) < O(n
    3
    ) < O(2n) < O(n!) < O(n
    n
    )

    二、Python中list和dict方法的时间复杂度

    1、list内置方法时间复杂度

    注意:上述的时间复杂度是最坏时间复杂度 

    2、dict内置方法时间复杂度

     注意:上述的时间复杂度是最坏时间复杂度 

    作者:iveBoy
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    数据库Mysql给用户赋予操作表的权限
    C# log4net日志分等级打日志
    C# 将字符串转为函数名
    C# winform无法拖动控件
    C# 程序获取管理员方法
    C# 生成程序目录避免生成多余的XML和pdb
    C# 快速获取一个月的天数或最后一天
    正则
    C# 根据服务名打开所在文件夹
    330 div+css Experience
  • 原文地址:https://www.cnblogs.com/shenjianping/p/14418297.html
Copyright © 2020-2023  润新知