《数据结构与算法》一:时间复杂度

708 阅读1分钟

本系列文章是以笔记的方式进行记录,主要内容均来源于王争老师的《数据结构与算法之美》

时间复杂度

什么是数据结构,什么是算法

  • 数据结构:数据结构就是指一组数据的存储结构
  • 算法:算法就是操作数据的一组方法

数据结构是为算法服务的,算法要作用在特定的数据结构之上

什么是时间复杂度、空间复杂度

时间复杂度和空间复杂度是衡量算法代码的执行效率的指标。

常见的复杂度:O(1)O(logn)O(n)O(nlogn)O(n2)O(nk)O(2n)O(1)、O(logn)、O(n)、O(nlogn)、O(n^2)、O(n^k)、O(2^n)

什么是时间复杂度

如代码:

 int demo(int n) {
   int sum = 0;
   int i = 1;
   for (; i <= n; ++i) {
     sum = sum + i;
   }
   return sum;
 }

假设每行代码执行的时间都一样,为 unit_time。

第 2、3 行代码分别需要 1 个 unit_time 的执行时间,第 4、5 行都运行了 n 遍,所以需要 2n*unit_time 的执行时间,所以这段代码总的执行时间就是 (2n+2)*unit_time。可以看出来,所有代码的执行时间 T(n) 与每行代码的执行次数成正比。 T(n)=(2n+2)T(n)=(2n+2)*unit_time

我们吧unit_time和其他一些干扰项都归纳为O。 那么上面公式就简化为: T(n)=O(2n+2)T(n) = O(2n+2)

我们假设n趋向无限大,那么公司中的2就可以忽略了。 最后公式简化为: T(n)=O(n)T(n) = O(n)

我们再看一个例子:

 int demo(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;
     }
   }
 }

上面这个例子试着自己考虑一下他的时间复杂度是多少?

思考时间。。。

思考时间。。。

思考时间。。。

答案公布:
第一步:T(n)=(2n2+2n+3)T(n) = (2n^2+2n+3)*unit_time
第二部:T(n)=O(2n2+2n+3)T(n) = O(2n^2+2n+3)
第三部:T(n)=O(n2)T(n) = O(n^2)

我们在扩充两个例子,如:
T(n)=O(n)+O(n2)=O(n2)T(n) = O(n) + O(n^2) = O(n^2)
T(n)=O(n)O(n2)=O(n3)T(n) = O(n) * O(n^2) = O(n3)\

几种常见时间复杂度实例

  1. 常量阶O(1)O(1)
 int i = 8;
 int j = 6;
 int sum = i + j;

一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1)。

  1. 对数阶、线性对数阶O(logn)O(nlogn)O(logn)、O(nlogn)
 i=1;
 while (i <= n)  {
   i = i * 2;
 }

转化上面的代码为公式:
当n=1时:O(n)=20=1O(n) = 2^0 =1
当n=2时:O(n)=21=2O(n) = 2^1 = 2
当n=4是:O(n)=23=4O(n) = 2^3 = 4
由上面得出代码运行次数是2运行次)=n2^(运行次数^)=n, 那么经过对数转化:运行次数T(n)=O(log2n)T(n) = O(log_2n)
如果上面的代码变为i = i * 3,那么运行次数T(n)=O(log3n)T(n) = O(log_3n) 又因为对数转化原则(如下图),log3n就等于log32log2n,其中log32log_3n 就等于 log_3 2 * log_2n,其中 log_3 2 是一个常量,忽略掉,所以 O(log3n)=O(log2n)O(log_3n) = O(log_2n),因此,在对数阶时间复杂度的表示方法里,我们忽略对数的“底”,统一表示为 O(logn)O(logn)

对log的换底公式不了解的同学可以参考这个

  1. 常规阶O(m+n)、O(m*n)
int demo(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 是表示两个数据规模。我们无法事先评估 m 和 n 谁的量级大,所以我们在表示复杂度的时候,就不能简单地利用加法法则,省略掉其中一个。所以,上面代码的时间复杂度就是 O(m+n)。

以上就是时间复杂度的笔记。下一篇我们学习空间复杂度。觉得好的同学可以关注我哦,大概每周更新一篇。

本系列其他文章:
《数据结构与算法》目录