数据结构和算法复杂度分析(上)

Posted php吧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构和算法复杂度分析(上)相关的知识,希望对你有一定的参考价值。

一、什么是复杂度分析?
1.数据结构和算法解决是“如何让计算机更快时间、更省空间的解决问题”。
2.因此需从执行时间和占用空间两个维度来评估数据结构和算法的性能。
3.用时间复杂度和空间复杂度两个概念来描述性能问题,二者统称为复杂度。
4.复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系。

二、为什么要进行复杂度分析?
1.和性能测试相比,复杂度分析有不依赖执行环境、成本低、效率高、易操作、指导性强的特点。
2.掌握复杂度分析,将能编写出性能更优的代码,有利于降低系统开发和维护成本。

三、如何进行复杂度分析?
1.大O表示法
1)来源
算法的执行时间与每行代码的执行次数成正比,用T(n) = O(f(n))表示,其中T(n)表示算法执行总时间,f(n)表示每行代码执行总次数,而n往往表示数据的规模。对于表达式中的常数一般都不用考虑,直接去掉。比如f(n) = 2*n^2+3,那么我们只需要考虑上n的情况,f(n)=n^2,也就是T(n)=O(n^2)。
2)特点
以时间复杂度为例,由于时间复杂度描述的是算法执行时间与数据规模的增长变化趋势,所以常量阶、低阶以及系数实际上对这种增长趋势不产决定性影响,所以在做时间复杂度分析时忽略这些项。
2.复杂度分析法则
1)单段代码看高频:比如循环。

 int cal(int n) {

   int sum = 0;

   int i = 1;

   for (; i <= n; ++i) {

     sum = sum + i;

   }

   return sum;

 }

这段代码的时间复杂度为O(n)。


2)多段代码取最大:比如一段代码中有单循环和多重循环,那么取多重循环的复杂度。

int cal(int n) {

   int sum_1 = 0;

   int p = 1;

   for (; p < 100; ++p) {

     sum_1 = sum_1 + p;

   }


   int sum_2 = 0;

   int q = 1;

   for (; q < n; ++q) {

     sum_2 = sum_2 + q;

   }

 

   int sum_3 = 0;

   int i = 1;

   int j = 1;

   for (; i <= n; ++i) {

     j = 1; 

     for (; j <= n; ++j) {

       sum_3 = sum_3 +  i * j;

     }

   }

 

   return sum_1 + sum_2 + sum_3;

 }

上述代码一共分3个代码段,第一段求sum_1,时间复杂度是O(1),第二段sum_2的时间复杂度是O (n),第三段sum_3的时间复杂度是O(n^2),所以从多段代码取最大特点来看,这段代码的时间复杂度就是O(n^2)。


3)嵌套代码求乘积:比如递归、多重循环等

int cal(int n) {

   int ret = 0; 

   int i = 1;

   for (; i < n; ++i) {

     ret = ret + f(i);

   } 

 } 

 

 int f(int n) {

  int sum = 0;

  int i = 1;

  for (; i < n; ++i) {

    sum = sum + i;

  } 

  return sum;

 }

f函数的时间复杂度是O(n),第一段代码的时间复杂度也是O(n),但第一段代码中的每次循环都调了一次f函数,所以这段代码的时间复杂度上O(n) * O(n) = O(n*n) = O(n^2)。


4)多个规模求加法:比如方法有两个参数控制两个循环的次数,那么这时就取二者复杂度相加。

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)+O(n),也就可以看作是关于m和n的函数。


四、常用的复杂度级别?
多项式阶:随着数据规模的增长,算法的执行时间和空间占用,按照多项式的比例增长。包括,
O(1)(常数阶)、O(logn)(对数阶)、O(n)(线性阶)、O(nlogn)(线性对数阶)、O(n^2)(平方阶)、O(n^3)(立方阶)

非多项式阶:随着数据规模的增长,算法的执行时间和空间占用暴增,这类算法性能极差。包括,
O(2^n)(指数阶)、O(n!)(阶乘阶)

五、如何掌握好复杂度分析方法?
复杂度分析关键在于多练,所谓孰能生巧。

以上是关于数据结构和算法复杂度分析(上)的主要内容,如果未能解决你的问题,请参考以下文章

01 | 复杂度分析(上):如何分析统计算法的执行效率和资源消耗?

入门篇1 # 复杂度分析(上):如何分析统计算法的执行效率和资源消耗?

入门篇1 # 复杂度分析(上):如何分析统计算法的执行效率和资源消耗?

入门篇1 # 复杂度分析(上):如何分析统计算法的执行效率和资源消耗?

Chapter3 复杂度分析(上):如何分析,统计算法的执行效率和资源消耗

复杂度分析(上):如何分析统计算法的执行效率和资源消耗