[笔记]《数据结构与算法之美》的第04课:复杂度分析(下):浅析最好、最坏、平均、均摊时间复杂度


这是我学习《数据结构与算法之美》的第04课:复杂度分析(下):浅析最好、最坏、平均、均摊时间复杂度

课程原文链接可点击此处.

当一段循环代码中有特殊的情况会提前退出循环的时候,代码的时间复杂度就可以算得再细一些,比如这段代码:

// 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;
}

最好、最坏情况时间复杂度

最好和最坏时间复杂度,其实是给出了一段代码运算时间的范围、上下限,这个数据在某些情况下可能会比较有用,比如系统的响应时间上限这类情况,可以提前预估最坏情况下的风险。

举例:给领导汇报的时候,经常会说我这个代码最快0.01毫秒就能算出来,最慢也只需要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;
}

这段代码中,x 是唯一的变量,x 在 array 中的位置决定了这段代码啥时候结束。x 在 array 中的位置有 n 种情况,还有1种情况是 x 不在 array 中,总共 n+1 种可能。假设这 n+1 种可能出现的概率是平均的,那么这段代码种 for 循环总共运行的次数为 (1+2+3+…+n+n)/(n+1) = (n2+3n)/2(n+1),省略掉系数、常量、低阶的因素,这个平均时间复杂度就是 O(n)。

均摊时间复杂度


 // array表示一个长度为n的数组
 // 代码中的array.length就等于n
 int[] array = new int[n];
 int count = 0;
 
 void insert(int val) {
    if (count == array.length) {
       int sum = 0;
       for (int i = 0; i < array.length; ++i) {
          sum = sum + array[i];
       }
       array[0] = sum;
       count = 1;
    }

    array[count] = val;
    ++count;
 }

上面这段代码,假设 val 插入到 array 的位置概率相等,有 n+1种可能,平均时间复杂度是 O(1);但这代码有个规律,它的时间复杂度是 O(1) + O(1) + …n个O(1) + O(n) + O(1) + O(1) + …n个O(1) + O(n) 这么一串有规律的复杂度组成的,可以换种思路,不考虑平均时间复杂度了,而是将每个O(n)的时间平摊到前面的 n 个 O(1) 身上,是不是就都变成常量级的了?这就是均摊时间复杂度的思路。

均摊时间复杂度在特定的场景才能均摊。

思考题


// 全局变量,大小为10的数组array,长度len,下标i。
int array[] = new int[10]; 
int len = 10;
int i = 0;

// 往数组中添加一个元素
void add(int element) {
   if (i >= len) { // 数组空间不够了
     // 重新申请一个2倍大小的数组空间
     int new_array[] = new int[len*2];
     // 把原来array数组中的数据依次copy到new_array
     for (int j = 0; j < len; ++j) {
       new_array[j] = array[j];
     }
     // new_array复制给array,array现在大小就是2倍len了
     array = new_array;
     len = 2 * len;
   }
   // 将element放到下标为i的位置,下标i加一
   array[i] = element;
   ++i;
}

上面代码中,add 方法的最好时间复杂度为 O(1),最坏时间复杂度为 O(n),平均时间复杂度为 O(1),这个是可以平摊的,平摊时间复杂度为O(1)。

参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值