zoukankan      html  css  js  c++  java
  • 一文概括复杂度分析

    6217760-c5d5141d75bbb777.jpg

    复杂度分析法则:

    • [单段代码看频率]:看代码片段中「循环代码」的时间复杂度。

    • [多段代码看最大]:如果多个 for 循环,看「嵌套循环最多」的那段代码的时间复杂度。

    • [嵌套代码求乘积]:循环、递归代码,将内外嵌套代码求乘积去时间复杂度。

    • [多个规模求加法]:法有两个参数控制两个循环的次数,那么这时就取二者复杂度相加。

    ----------------------------------❤------------------------------------

    时间复杂度

    1、什么是复杂度?

    所有代码的执行时间 T(n)与每行代码的执行次数n成正比【T(n) = O(f(n)) 】。

    2、分析的三个方法

    最多法则

    忽略掉公式中的常量、低阶、系数,取最大循环次数就可以了,也就是循环次数最多的那行代码。

    Example:

    // 求n个数字之和
    int xiaolu(int n) {
       int sum = 0;
       for (int i = 1; i <= n; ++i) {
         sum = sum + i;
       }
       return sum;
     }
    

    分析:

    第二行是一行代码,也就是常量级别,与 n 没有关系,可以忽略,四、五行代码是我们重点分析对象,与 n 有关,时间复杂度就是反映执行时间和 n 数据规模的关系。求 n 个数据之和需要执行 n 次。所以时间复杂度为 O(n)。

    加法法则

    总复杂度等于循环次数最多的那段复杂度。

    Example:

    int xiaolu(int n) {
        int sum = 0;
        //循环一
        for (int i = 1; i <= 100; j++) {
          sum = sum + i;
        }
        //循环二
        for (int j = 1; j <= n; j++) {
           sum = sum + i;
       }
     }
    

    分析:
    上边有两个循环,一个循环 100 次,另一个循环 n 次,我们选择循环次数最多的那一个且和「数据规模 n 」相关的循环。由上可知,我们很容易选出循环二,即和数据规模 n 有关,循环次数最多,循环次数最多的那段代码时间复杂度就代表总体的时间复杂度,为 O(n) ;

    乘法法则

    当我们遇到嵌套的 for 循环的时候,怎么计算时间复杂度呢?那就是内外循环的乘积。

    Example:

     for (int j = 1; j <= n; j++) {
         for(int i = 1; i <= n; i++)
         sum = sum + i;
     }
    

    分析:

    外循环一次,内就循环 n 次,那么外循环 n 次,内就循环 n*n 次。所以时间复杂为 O(n²)。

    空间复杂度

    1、什么是空间复杂度?

    表示算法的「存储空间」与「数据规模」之间的增长关系.

    Example:

     int xiaolu(int n) {
        int sum = 0;
        //循环一
        for (int i = 1; i <= 100; j++) {
          sum = sum + i;
        }
        //循环二
        for (int j = 1; j <= n; j++) {
           sum = sum + i;
       }
     }
    

    分析:

    在所有代码中,我们很容易寻找到存储空间相关的代码,就是第二行,申请了一个 n 大小的存储空间,所以空间复杂度为 O(n)。

    2、最常见的空间复杂度

    O(1)、O(n)、O(n²)。

    O(1)

    常量级的时间复杂度表示方法,无论是一行代码,还是多行,只要是常量级的就用 O(1) 表示。

    Example:

    int i = 1;
    int j = 2;
    int sum = i + j;
    

    分析:

    因为这三行代码,也就是常量级别的代码不随 n 数据规模的改变而改变。(循环、递归除外)

    O(logn) | O(nlogn)

    「对数阶时间复杂度」,最难分析的一种时间复杂度。

    Example:

     i=1;
     while (i <= n)  {
       i = i * 3;
     }
    

    分析:

    要求这段代码的时间复杂度就求这段代码执行了多少次,看下图具体分析。

    6217760-532f23c9e150a7ce.jpg

    补充:
    不管是以 2 为底、以 3 为底,还是以 10 为底,可以把所有对数阶的时间复杂度都记为 O(logn),因为对数之间可以转换的,参照高中课本

    O(m+n) | O(mn)*

    参照上边讲到的加法和乘法法则。

    ----------------------------------❤------------------------------------

    1、最好、最坏时间复杂度

    所谓的最好、最坏时间复杂度分别对应代码最好的情况和最坏的情况下的执行。

    Example

     //在一个 array 数组中查找一个数据 a 是否存在
    for (int i = 1; i < n; i++) {
        if (array[i] == a) {
           return i;
        }
     }
    

    分析:

    1、最好情况就是数组的第一个就是我们要查找的数据,上边代码之执行一遍就可以,这种情况下的时间复杂度为最好时间复杂度,为 O(1)。

    2、最坏的情况就是数组的最后一个才是我们要查找的数据,需要循环遍历 n 遍数组,也就对应最坏的时间复杂度为 O(n) 。

    2、平均时间复杂度

    平均时间复杂度需要借助概率论的知识去分析,也就是我们概率论中所说的加权平均值,也叫做期望值。

    分析:

    比如上方的例子,假设我们查找的数据在数组中的概率为 1/2;出现在数组中的概率为 n/1,根据下边的公式就可以算出出现的概率为 1/2n 。

    6217760-f5832c2707175b3e.jpg

    然后我们再把每种情况考虑进去,就可以计算出平均时间复杂度。

    6217760-717934634ceb55fb.jpg

    3、均摊时间复杂度

    什么是均摊时间复杂度?

    比如我们每 n 次插入数据的时间复杂度为 O(1),就会有一次插入数据的时间复杂度为 O(n),我们将这一次的时间复杂度平均到 n 次插入数据上,时间复杂度还是 O(1)。

    适用场景

    一般应用于某一数据结构,连续操作时间复杂度比较低,但是个别情况时间复杂度特别高,我们将特别高的这一次进行均摊到较低的操作上。

    几种复杂度性能对比

    各个时间复杂度的性能


    6217760-21006321b67eb3f1.jpg

    ===========我是华丽的分割线===========


    更多知识:
    点击关注专题:嵌入式Linux&ARM

    或浏览器打开:https://www.jianshu.com/c/42d33cadb1c1

    或扫描二维码:

    6217760-e6bba06e005d8fe7.jpg

  • 相关阅读:
    对MFC文档、视图、框架的理解
    MFC中快速将CVIew转换成CScrollView
    MFC中的一个错误
    单文档中视图与文档的相互
    python函数
    python模块介绍和引入
    python面向对象和面向过程
    python数据类型2
    python数据类型
    python无法使用input功能
  • 原文地址:https://www.cnblogs.com/leon1124/p/14039775.html
Copyright © 2011-2022 走看看