算法复杂度分析(上)

142 阅读1分钟

数据结构和算法本身解决的是“快”和“省”的问题,即如何让代码运行得更快,如何让代码更省存储空间

  1. 如何来衡量编写的算法代码的执行效率呢?(使用时间、空间复杂度分析)

  2. 为什么需要复杂度分析?

    我们需要一个不用具体的测试数据来测试,就可以粗略的估计算法的执行效率的方法

    • 使用事后统计法(先跑代码后监控)
      1. 测试结果非常依赖测试环境(使用不同的机器测试算法代码,性能好的机器比性能差的机器执行的速度要快)
      2. 测试结果受数据规模的影响很大(同一个排序算法,在数据量为1000和100000执行时间差别很大)

渐进时间复杂度

简称(时间复杂度)是表示代码执行时间随数据规模增长的变化趋势

  • 特点(采用大O标记复杂度的时候,可以忽略常数阶、低阶、系数,因为这些对实际的增长趋势不产生决定性影响)
1. 分析算法的时间复杂度的时候只需要关注循环次数最多的那段代码
1  int cal(int n) {
2  int sum = 0;
3  int i = 1;
4  for (; i <= n; ++i) {
5    sum = sum + i;
6  }
7  return sum;
8  }
时间复杂度看4、5行,两行代码被执行了n次,所以总的时间复杂度为O(n) 
2. 加法法则:(总复杂度等于量级最大的那段代码的复杂度)
 1 int cal(int n) {
 2  int sum_1 = 0;
 3   int p = 1;
 4   for (; p < 100; ++p) {
 5     sum_1 = sum_1 + p;
 6   }
 7 
 8   int sum_2 = 0;
 9   int q = 1;
10   for (; q < n; ++q) {
11     sum_2 = sum_2 + q;
12   }
13 
14   int sum_3 = 0;
15   int i = 1;
16   int j = 1;
17   for (; i <= n; ++i) {
18     j = 1; 
19     for (; j <= n; ++j) {
20       sum_3 = sum_3 +  i * j;
21     }
22   }
23   return sum_1 + sum_2 + sum_3;
24  }

将上面的代码分为三部分第一部分(2~6行)时间复杂度为O(1),第二部分(8~12行)时间复杂度为O(n),第三部分(14~22行)时间复杂度为O(n^2), 根据加法法则总的时间复杂度为O(n^2)

3. 乘法法则:(嵌套代码的复杂度等于嵌套内外代码复杂度的乘积)
 1 int cal(int n) {
 2   int ret = 0; 
 3   int i = 1;
 4   for (; i < n; ++i) {
 5     ret = ret + f(i);
 6   } 
 7 } 
 8 
 9 int f(int n) {
10  int sum = 0;
11  int i = 1;
12  for (; i < n; ++i) {
13    sum = sum + i;
14  } 
15  return sum;
16 }
常用的复杂度分析
  • O(1)常量级时间复杂度的一种表示方法(一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1))

  • O(logn)、O(nlogn)

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

通过上面的代码我们可以得到2^x=n, 也就是x = log2n, 忽略系数可以得到复杂度为O(logn)。O(nlogn)其实就是执行了n次的O(logn)

  • O(m+n)、O(m*n) (代码复杂度,由两个数据的规模来决定)
int cal(int m, int n) {
 int sum_1 = 0;
 int i = 1;
 for (; i < m; ++i) {
   sum_1 = sum_1 + i;
 }

 int sum_2 = 0;
 int j = 1;
 for (; j < n; ++j) {
   sum_2 = sum_2 + j;
 }

 return sum_1 + sum_2;
}

因为无法评估m和n谁的量级大,所以就不能利用加法法则省略其中一个,所以代码的复杂度为O(m+n)

常见的复杂度的级别

O(1)(常数阶)< O(logn)(对数阶)< O(n)(线性阶)> O(nlogn)(线性对数阶)> O(n^2)(平方阶)> O(n^3)(立方阶)

渐进空间复杂度

简称(空间复杂度)表示算法的存储空间与数据规模之间的增长关系。

总结

复杂度分析并不难,关键在于多练。

学习算法的总结@王争(数据结构与算法之美)