zoukankan      html  css  js  c++  java
  • [数据结构与算法 03] 最好、最坏、平均、均摊 时间复杂度

    参考:https://time.geekbang.org/column/article/40036

    由来

    • /****
          在一个无序的数组(array)中
          查找变量 x 第一次出现的位置。如果没有找到,就返回 -1
      ****/
      
      // n 表示数组array的长度
      int find(int[] array, int n, int x) {
          int i = 0;
          int pos = -1;
          for (; i < n; ++i) {
              if (array[i] == x) pos = i;
          }
          return pos;
      }

    分析出此函数的时间复杂度为 O(n)

    • 在数组中查找一个数据,并不需要每次都把整个数组都遍历一遍,
    • 因为有可能中途找到就可以提前结束循环了。

    所以我们可以这样优化一下这段查找代码

    • /****
          在一个无序的数组(array)中
          查找变量 x 第一次出现的位置。如果没有找到,就返回 -1
      ****/
      
      // n 表示数组array的长度
      int find(int[] array, int n, int x) {
          int i = 0;
          int pos = -1;
          for (; i < n; ++i) {
              if (array[i] == x) {
                  pos = i;
                  break; // 已经找到了,就不必继续找了
              }
          }
          return pos;
      }

    那么问题来了,如此优化以后,时间复杂度还是 O(n) 吗???

    • 可能第一次就找到了,只循环了一次,那时间复杂度就是 O(1)
    • 可能最后一次才找到,循环了 n 次,时间复杂度就成了 O(n)

    所以,不同的情况下,这段代码的时间复杂度是不一样的

    因此,为了表示代码在不同情况下的不同时间复杂度,我们需要引入三个概念

    • 最好情况时间复杂度
    • 最坏情况时间复杂度
    • 平均情况时间复杂度

     

    一、最好情况 时间复杂度(best case time complexity)

    在最理想的情况下,执行这段代码的时间复杂度

    "只循环一次就找到了"

     

    二、最坏情况 时间复杂度(worst case time complexity)

    在最糟糕的情况下,执行这段代码的时间复杂度

    "循环了 n 次才找到"

     

    三、平均情况 时间复杂度(average case time complexity)

    最好情况时间复杂度 和 最坏情况时间复杂度 对应的都是极端情况下的代码复杂度,发生的概率其实并不大

    为了更好地表示平均情况下的复杂度,我们需要引入另一个概念:平均情况时间复杂度,后面我简称为平均时间复杂度

    思考

    1. 要查找的变量 x 在数组中的位置,有 n+1 种情况: 在数组的 0~n-1 位置中和不在数组中
    2. 我们把每种情况下,查找需要遍历的元素个数累加起来,
    3. 然后再除以 n+1,就可以得到需要遍历的元素个数的平均值,即

    时间复杂度的大 O 标记法中,可以省略掉系数、低阶、常量,所以,咱们把刚刚这个公式简化之后,得到的平均时间复杂度就是 O(n)

    结论虽然是正确的,但是计算过程稍微有点儿问题。究竟是什么问题呢?

    我们刚讲的这 n+1 种情况,出现的概率并不是一样的。

    我带你具体分析一下。(这里要稍微用到一点儿概率论的知识,不过非常简单,你不用担心。)

    • 我们知道,要查找的变量 x,要么在数组里,要么就不在数组里。
    • 这两种情况对应的概率统计起来很麻烦,为了方便你理解,我们假设在数组中与不在数组中的概率都为 1/2。
    • 另外,要查找的数据出现在 0~n-1 这 n 个位置的概率也是一样的,为 1/n。

    所以,根据概率乘法法则,要查找的数据出现在 0~n-1 中任意位置的概率就是 1/(2n)

    如果我们把每种情况发生的概率也考虑进去,那平均时间复杂度的计算过程就变成了这样

    这个值就是概率论中的加权平均值,也叫作期望值,

    所以平均时间复杂度的全称应该叫加权平均时间复杂度或者期望时间复杂度

     

    四、均摊 时间复杂度(amortized time complexity)

    均摊时间复杂度应用的场景比上面三种更加特殊、更加有限

    一般均摊时间复杂度就等于最好情况时间复杂度

     

    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    C++强大的背后
    C++ 非托管的vc工程中部分文件使用.Net Framwork
    C++ 基于 Visual C++6.0 的 DLL 编程实现
    C++ 中指针,指针的引用,指针的指针的区别
    C# 中重用c/c++旧模块
    C++ 打开exe文件的方法(VS2008)
    C++ 指针 指针高级<高质量编程>
    C++ 函数指针
    有用但不常见的c++函数
    C++ int & *p; //不能建立指向引用的指针;int *a; int * & p=a; //正确,指针变量的引用
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/12285954.html
Copyright © 2011-2022 走看看