复杂度分析(2)

// n 表示数组 array 的长度
int find(int[] array, int x) {
  int i = 0;
  int pos = -1;
  int n = array.length;
  for (; i < n; ++i) {
    if (array[i] == x) {
       pos = i;
       break;
    }
  }
  return pos;
}

如上所示代码,查询array数组里等于x的元素,找到返回数组元素对应的下标,数组长度为n。

最好时间复杂度,最坏时间复杂度分析

由代码我们可以看出,
当x元素在数组第一个位置时,for循环代码执行一次就结束了,时间复杂度为O(1)。
当x元素在数组最后一位时,for循环执行了n次,时间复杂度为O(n),
因此代码在不同情况下,具有不同的时间复杂度。为O(1)叫最好时间复杂度,O(n)叫最坏时间复杂度,有最好最坏自然就有平均时间复杂度。

平均时间复杂度分析

在数组中查找x有n+1种情况,0-n-1和x不在数组中,我们把每种情况下需要遍历的元素个数加起来(如x在第一位时遍历一次,在最后一位,遍历n次,不在数组中,也遍历n次),再除以n+1,就可以得到平局遍历元素次数。
每种情况下遍历元素个数总和:1+2+3+…+n+n=n*(n+3)/2

(n*(n+3)/2)/n+1 = 1/2 * n + n * (n+1)

省略掉系数,低阶,常量,平均时间复杂度为O(n)

上面计算的平均时间复杂度还没有考虑到各种情况发生的概率,假设x在数组中和不在数组中概率都为1/2,x出现在0到n-1这n个位置概率为n-1,当x在数组中时,每个元素为x的可能性为1/2n。
平均复杂度计算就变成了这样:

1 * (1/2n) + 2 * (1/2n) + 3 * (1/2n) + ...... + n * (1/2n) + n * (1/2) = (3n + 1)/4

时间复杂度还是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;
 }


这段代码实现了一个往数组中插入数据的功能。当数组满了之后,也就是
count == array.length时,遍历数组,求数组所有元素之和,放入数组第一个元素,清空数组。如果数组有空间则直接将数据插入数组。

最好时间复杂度:
数组还有空间,直接插入数组,复杂度为O(1)
最坏时间复杂度:
数组已满,需要进行for循环,复杂度为O(n)
平均时间复杂度:
数组长度为n,插入数据的插入位置情况有n种,每种复杂度都为O(1),不执行for循环,还有一种情况,数组满了,此时复杂度为O(n),一共有n+1中情况。求平均复杂度公式为:

1 * 1/(n+1) + 1 * 1/(n+1) + ....... + 1 * 1/(n+1) + n * 1/(n+1) = 2 - 2/(n+1)

平均时间复杂度为 O(1).

均摊时间复杂度分析:
由代码可看出,没进行一次O(n)操作,都会有n-1 次O(1)操作,我们把耗时多的O(n)次操作,均摊给n-1次的O(1)次操作,这样平均复杂度就很好算了,为O(1)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值