数据结构与算法之美 | 学习笔记一 —— 复杂度分析

事后统计法干扰因素多,例如处理器速度、测试数据规模等。因此采用复杂度分析。

一、时间复杂度

1.大O时间复杂度表示法

大O表示代码执行时间随数据规模增长的变化趋势,所以叫渐进时间复杂度(asymptotic time complexity)。所有代码的执行时间T(n)与每行代码的执行次数成正比,即大O时间复杂度表示法 T ( n ) = O ( f ( n ) ) T(n) = O(f(n)) T(n)=O(f(n)),其中 f ( n ) f(n) f(n)表示每行代码执行次数总和。例如:

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

第2、3、4行 = 3;第5、6行 = 2n;第7、8行 = 2 n 2 2n^2 2n2;因此上面代码 T ( n ) = ( 2 n 2 + 2 n + 3 ) ∗ u n i t T i m e T(n) = (2n^2+2n+3)*unitTime T(n)=(2n2+2n+3)unitTime. 利用公式, T ( n ) = O ( 2 T(n) = O(2 T(n)=O(2n^2 + 2 n + 3 ) +2n+3) +2n+3)

只记录最大量级,即 T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2)。其中嵌套循环复杂度是嵌套内外代码复杂度的乘积。

2.量级排序

O ( 1 ) < O ( l o g ( n ) ) < O ( n ) < O ( n l o g ( n ) ) < O ( n k ) < O ( 2 n ) < o ( n ! ) O(1)<O(log(n))<O(n)<O(nlog(n))<O(n^k)<O(2^n)<o(n!) O(1)<O(log(n))<O(n)<O(nlog(n))<O(nk)<O(2n)<o(n!)
其中 O ( 2 n ) O(2^n) O(2n) o ( n ! ) o(n!) o(n!)为非多项式量级(Non-Deterministic Polynomial)。

(1) O ( l o g ( n ) ) O(log(n)) O(log(n))

其中 O ( l o g ( n ) ) O(log(n)) O(log(n))举例,下面代码执行次数 x x x 2 x = n 2^x = n 2x=n, 即为 O ( l o g 2 n ) O(log_2n) O(log2n)

 i=1;
 while (i <= n)  {
   i = i * 2;
 }
(2) O ( m + n ) O(m+n) O(m+n)

代码中有两个数据规模。

二、空间复杂度

渐进空间复杂度(asymptotic space complexity),表示算法的存储空间与数据规模之间的增长关系。
看的是申请空间存储变量的规模。常见为 O ( 1 ) , O ( n ) , O ( n 2 ) O(1),O(n),O(n^2) O(1),O(n),O(n2)

三、最好、最坏、平均和均摊情况时间复杂度

下面代码最好情况时间复杂度为 O ( 1 ) O(1) O(1),最坏为 O ( n ) O(n) O(n)
平均时间复杂度应该计算为加权平均时间复杂度,用概率论的方法, O ( ( 3 n + 1 ) / 4 ) O((3n+1)/4) O((3n+1)/4)

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

均摊时间复杂度即将耗时多的操作均摊到耗时少的操作中,一般情况下这个值等于最好情况时间复杂度。
例如:


// 全局变量,大小为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;
}

上面例子,最好情况时间复杂度为 O ( 1 ) O(1) O(1),最坏为 O ( n ) O(n) O(n),均摊为 O ( 1 ) O(1) O(1)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值