1.复杂度分析

作者: think91 | 来源:发表于2020-01-13 15:53 被阅读0次

数据结构算法概览图

913e0ababe43a2d57267df5c5f0832a7.jpg

一、关于复杂度分析

大O表示法

这里有段非常简单的代码,求 1,2,3…n 的累加和。现在,我们一块来估算一下这段代码的执行时间。

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  }

我们这里假设每行代码执行的时间都一样,为 unit_time , 那这段代码总的执行时间就是 (2n+2)*unit_time 。大O 表示法是表示这里的N 与总时间的关系,由该公司我们可以得出总时间与N的关系是成正比的,所有我们得出T(n)=O(f(n)) , 我们记为 O(n)

O(n)分析法

只关注循环执行次数最多的一段代码 : 大 O 这种复杂度表示方法只是表示一种变化趋势 ,所以通常会忽略掉公式中的常量、低阶、系数,只需要记录一个最大阶的量级就可以了,我们在分析一个算法、一段代码的时间复杂度的时候,也只关注循环执行次数最多的那一段代码就可以了
乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积 , 公式为T1(n) = O(n),T2(n) = O(n2),则 T1(n) * T2(n) = O(n3) 。落实到代码就是嵌套循环

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

几种常见时间复杂度实例分析

O(1)
O(1) 只是常量级时间复杂度的一种表示方法,并不是指只执行了一行代码。即便有 1000 行,它的时间复杂度也是 O(1),而不是 O(1000) ,表示的是总执行复杂度不随变量N的变化而变化 。

O(logn)、O(nlogn)
对数阶时间复杂度非常常见,同时也是最难分析的一种时间复杂度。最常见典型的O(logN)复杂度就是二分查找,每查找一次,剩下的数据量成倍减少,2^x=n ,解 x 这个问题高中我们学过 x=log2n 。所以二分查询这段代码的时间复杂度就是 O(log2n) = O(logN) , 而O(nlogN)就是O(logN) 的复杂度需要执行 N 次 ,常见为快速排序,归并排序,堆排这些。

O(m+n)、O(m*n)
m 和 n 是表示两个数据规模。我们无法事先评估 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;
}

时间复杂度映射

时间复杂度关系图.png

最好,最坏,平均,均摊时间度分析

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

上面代码在一个无序的数组(array)中,查找变量 x 出现的位置,如果找到后就结束,如果数组中第一个元素正好是要查找的变量 x , 那时间复杂度就是 O(1),但如果数组中不存在变量 x,那我们就需要把整个数组都遍历一遍,时间复杂度就成了 O(n),所以,不同的情况下,这段代码的时间复杂度是不一样的。所以最好情况时间复杂度就是,在最理想的情况下,执行这段代码的时间复杂度,最坏情况时间复杂度就是,在最糟糕的情况下,执行这段代码的时间复杂度。平均时间复杂度分析稍微复杂,像这段代码,我们假设数组中存在和不存在该数的概率都是1/2。那计算公式变成 1*1/2n + 2*1/2n + 3*1/2n + ...n*1/2n+n*1/2 = 3n+1/4 = O(n)。均摊复杂度分析是一种特殊的平均时间复杂度,比如在java中的ArrayList 中的add 操作,假设我们现在对N个数据进行add操作,不考虑扩容情况很容易想到时间复杂度为O(n) ,但ArrayList当存储空间满的时候会开一个新的数组将元数据搬迁到新数组,也就是说我们在add操作时,其中有n-1个时间复杂度为O(1) ,有一个时间复杂度为O(n) ,均摊分析法是将这一个O(n)的时间复杂度均分到之前O(1)上,这样每个的复杂度为O(2) ,最后添加N个数据时间复杂度还为O(n)

空间复杂度分析

空间复杂度同样表示算法的存储空间与数据规模之间的增长关系,值得注意的是空间复杂度是指随着数据增长你额外开辟的内存空间。

总结

复杂度分析是一种对代码执行效率的粗略估计,同样的复杂度可能执行效率差别会比较大,甚至一些情况下O(n)比O(1)执行时间更短,分析时间复杂度的过程可以使我们会有代码效率优化的意识和方向。

相关文章

  • 一个好的算法如何测评

    一个算法的好坏可以根据复杂度分析来测评. 复杂度分析包括时间复杂度和空间复杂度. 1.时间复杂度 需要考虑: 1)...

  • 1.复杂度分析

    数据结构算法概览图 一、关于复杂度分析 大O表示法 这里有段非常简单的代码,求 1,2,3…n 的累加和。现在,我...

  • 递归树——借助树来求解递归算法的时间复杂度

    递归代码的时间复杂度分析起来非常麻烦,今天我们尝试来借助递归树分析递归算法的时间复杂度。 1. 递归树与时间复杂度...

  • 常用的算法笔记

    1.冒泡排序 算法分析 平均时间复杂度:O(n2) 空间复杂度:O(1) (用于交换) 稳定性:稳定 优化分析 如...

  • map:169.求众数(投票算法)

    求众数 哈希Map 复杂度分析 时间复杂度:O(N) 空间复杂度: O(N) 投票算法 复杂度分析

  • 复杂度分析-下

    复杂度分析的四个概念 1.最坏情况时间复杂度   代码在最理想情况下执行的时间复杂度。 2.最好情况时间复杂度  ...

  • 复杂度分析

    为什么需要复杂度分析? 大O复杂度表示法 时间复杂度分析 常见复杂度量级 复杂度量级简单说明 空间复杂度 时间复杂...

  • 2021-05-12

    数据复杂度分析 数据结构和算法本身解决的快和省的问题; 如何衡量的代码的执行效率;时间、空间复杂度分析。 1. 测...

  • 时间复杂度概念,最好,最坏,平均,均摊时间复杂度区别

    一、复杂度分析的4个概念 1.最坏情况时间复杂度:代码在最理想情况下执行的时间复杂度。2.最好情况时间复杂度:代码...

  • 复杂度分析

    一、复杂度分析的4个概念 1.最坏情况时间复杂度:代码在最理想情况下执行的时间复杂度。 2.最好情况时间复杂度:代...

网友评论

    本文标题:1.复杂度分析

    本文链接:https://www.haomeiwen.com/subject/wiegactx.html