Fork me on GitHub

算法时间复杂度

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

(一)引出算法

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

如果 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内置方法时间复杂度

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

 

posted @ 2021-02-21 12:23  iveBoy  阅读(754)  评论(0编辑  收藏  举报
TOP