• 时间复杂度与空间复杂度


    1 前言

    算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别。那么我们应该如何去衡量不同算法之间的优劣呢?

    主要还是从算法所占用的「时间」和「空间」两个维度去考量。

    • 时间维度:是指执行当前算法所消耗的时间,我们通常用「时间复杂度」来描述。
    • 空间维度:是指执行当前算法需要占用多少内存空间,我们通常用「空间复杂度」来描述。

    因此,评价一个算法的效率主要是看它的时间复杂度和空间复杂度情况。然而,有的时候时间和空间却又是「鱼和熊掌」,不可兼得的,那么我们就需要从中去取一个平衡点。

    2 时间复杂度

    1. 一般情况下,算法中的基本操作语句的重复执行次数是问题规模 n 的某个函数,用 T(n)表示,若有某个辅助函数 f(n),使得当 n 趋近于无穷大时,T(n) / f(n) 的极限值为不等于零的常数,则称 f(n)是 T(n)的同数量级函数。记作 T(n)= O( f(n) ),称O( f(n) ) 为算法的渐进时间复杂度,简称时间复杂度。
    2. T(n) 不同,但时间复杂度可能相同。 如:T(n)=n²+7n+6 与 T(n)=3n²+2n+2 它们的 T(n) 不同,但时间复杂度相同,都为 O(n²)。
    3. 计算时间复杂度的方法:
    • 用常数 1 代替运行时间中的所有加法常数 T(n)=n²+7n+6 => T(n)=n²+7n+1
    • 修改后的运行次数函数中,只保留最高阶项 T(n)=n²+7n+1 => T(n) = n²
    • 去除最高阶项的系数 T(n) = n² => T(n) = n² => O(n²)

    常见的时间复杂度

    O 名称 举例
    1 常数阶 一次赋值
    log2n 对数阶 二分查找
    n 线性阶 线性查找
    nlog2n 线性对数阶 快速排序
    n^2 平方阶 两重循环
    n^3 立方阶 三重循环
    2^n 指数阶 递归求斐波那契数列
    n! 阶乘阶 旅行商问题

    说明:常见的时间复杂度有小到大依次排序,随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低

    1. 常数阶 O(1)

    无论代码执行了多少行,只要是没有循环等复杂结构,那这个代码的时间复杂度就都是O(1)。

    2. 对数阶 O(log2n)

    i = 1
    n = 1000
    while i < n:
        i = i * 2
    

    说明: 在while循环里面,每次都将 i 乘以 2,乘完之后,i 距离 n 就越来越近了。假设循环x次之后,i 就大于 n 了,此时这个循环就退出了,也就是说 2 的 x 次方等于 n,那么 x = log2n也就是说当循环 log2n 次以后,这个代码就结束了。因此这个代码的时间复杂度为:O(log2n) 。 O(log2n) 的这个 2 时间上是根据代码变化的,若 i = i * 3 ,则是 O(log3n) 。

    常见:二分查找

    3. 线性阶 O(n)

    for i in range(n):
        j += 1
    

    说明: 这段代码,for循环里面的代码会执行n遍,因此它消耗的时间是随着n的变化而变化的,因此这类代码都可以用O(n)来表示它的时间复杂度。

    4. 线性对数阶 O(nlog2n)

    for i in range(n):
        while j < n:
            j = j * 2
    

    说明: 线性对数阶O(nlogN) 其实非常容易理解,将时间复杂度为O(logn)的代码循环N遍的话,那么它的时间复杂度就是 n * O(logN),也就是O(nlogN)。

    5. 平方阶 O(n^2)

    for i in range(n):
        for j in range(n):
            x += 1
    

    说明: 平方阶O(n²) 就更容易理解了,如果把 O(n) 的代码再嵌套循环一遍,它的时间复杂度就是 O(n²),这段代码其实就是嵌套了2层n循环,它的时间复杂度就是 O(nn),即 O(n²) 。如果将其中一层循环的n改成m,那它的时间复杂度就变成了 O(mn)

    6. 立方阶 O(n^3)

    3次n循环

    7. k 次方阶 O(n^k)

    k次n循环

    3 空间复杂度

    1. 类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)定义为该算法所耗费的存储空间,它也是问题规模 n 的函数。
    2. 空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。有的算法需要占用的临时工作单元数与解决问题的规模 n 有关,它随着 n 的增大而增大,当 n 较大时,将占用较多的存储单元,例如快速排序归并排序算法, 基数排序就属于这种情况
    3. 在做算法分析时,主要讨论的是时间复杂度。 从用户使用体验上看,更看重的程序执行的速度。一些缓存产品(redis, memcache)和算法(基数排序)本质就是用空间换时间
  • 相关阅读:
    Python JSON的基本使用
    python socket函数详解
    python关于字符编码的基本操作
    关于git的一些简单命令
    CS和BS结构的优缺点
    Web测试详细点
    详解SESSION与COOKIE的区别
    如何测试一个网页登陆界面
    二层交换机、三层交换机和路由器的原理及区别
    LSA分类
  • 原文地址:https://www.cnblogs.com/LittlePanger/p/12626337.html
Copyright © 2020-2023  润新知