数据结构算法概览图

一、关于复杂度分析
大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)执行时间更短,分析时间复杂度的过程可以使我们会有代码效率优化的意识和方向。
网友评论