数据结构算法——算法复杂度分析
算法复杂度分为时间复杂度和空间复杂度
首先要清楚一点,大O表示法的时间复杂度高不代表程序运行时间长,空间复杂度高不代表占用空间多。
他们表示的是代码执行时间随着数据规模增长的变化趋势。和算法储存空间与数据规模之间的增长关系。
时间复杂度判断方法
1、只关注循环次数最多的一段代码
2、加法法则:总复杂度等于量级最大的那段代码的复杂度
3、乘法原则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
常见的复杂度量级(按数量级递增)
常量阶:O(1)
对数阶:O(logn)
线性阶:O(n)
线性对数阶:O(nlogn)
平方阶:O(n2)
...
k次方阶:O(nk)
指数阶:O(2n)
阶乘阶:O(n!)
实战分析几个常见的复杂度
1,O(1)
int i=8; int j=6; int sum=i+j;
这个的复杂度是O(1)而不是O(3),代表算法复杂度不随n的变化而变化
2,O(logn),O(nlogn)
i=1; while(i<=n) { i=i*2; }
这段代码循环次数应该是log2n。不管底数是几,都可以记为O(logn),因为log2n=log210*log10n。也就是都可以互相线性转化。直接略去。如果再让这个程序运行n遍,他就是O(nlogn)
3,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)
综上,利用那三个判断方法,很容易就可以判断。
空间复杂度的判断也一模一样。
再来理解几个概念
最好情况复杂度,最坏情况复杂度,平均时间复杂度,均摊时间复杂度
// 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; }
看这个代码,程序的运行次数跟数组里的值有关,可能运行一次就结束了,也可能运行n次才结束。取决于数组里存的值的排列。
这就显而易见的区分出了最好情况复杂度和最坏情况复杂度。
平均时间复杂度也就可以定义为运行的次数乘以这种情况的概率的和。也就是运行次数的期望值。
均摊时间复杂度使用的局限性很大。
比如一个函数又一次运行的复杂度是O(n),但是又有n-1次运行的复杂度是O(1)。这样的话把O(n)的复杂度均摊到n-1个O(1)上。所以他的均摊时间复杂度就还是O(1)
正在跟着一个数据结构算法课程学习,国庆出去玩已经拉下三节课了,我这两天尽快补回来,及时归纳总结。