一、算法复杂度的概念
1、空间复杂度
算法运行所需要的内存空间,它和算法每次运行的数据数目或者说程序段所需要的变量个数成正比。
2、时间复杂度:算法的主要衡量指标,它主要和算法实现所需要的指令个数成正比。在分析算法时间复杂度的时候,一般用O(读作大o符号)进行表示。
大O符号表示这样一种概念:某个算法他运行所需要的运算量的级别,大O符号的表示通常忽略常数项或者低次项而主要考察最高次项的运算量级别数。例子:
1 for(int i = 0;i<n;i++){ 2 //这里具体代码一 3 n++;//第一步 4 n--;//第二步 5 . 6 . 7 . 8 //第k步 9 }
这里的算法复杂度为:kn;由于这里k是常数,所以分析的时候一般忽略常数k,而直接表示为O(n);表示该算法只是和输入数据量的大小n有关,并且运算数量级为n。
再例如:当实际的算法运算复杂度为an^2+bn+k中,分析的时候通常会忽略低次项n和常数项k,另外a、b的系数也不用考虑,我们分析的时候,只是分析算法的运算的数量级而已;
3、空间VS时间:很多 时候,我们发觉,某个算法在改造之前和改造之后,会存在一种这样的关系:空间变小,时间必然变大;反之亦然。其实,空间复杂度和时间复杂度本来就是矛盾的,不可能在同时提高两者的,后面的算法总结中我会提到这个问题(装个逼咯)
二、常用算法关系与表达式之间的关系
1、logN(注意,算法分析中,通常lgN的意义和数学的lgN有区别,算法中lgN通常是表示log2 N(这里2为底数))的对应情况:
大规模问题中,每步都将问题规模缩小n倍(对应log中底数为n,例如二分法找最值的对应复杂度为lgN),则算法复杂度课用上面算式表示
(特别说明:lg2还有以下的含义:十进制表示为二进制所需要的位数,logk N:十进制表示为k进制所需要的位数)
2、N:输入的所有数据均需要全部处理方可解决问题的情形
3、Nlogn N:1和2情况的组合,它表示如下意义:大规模问题进行n步分解后,每步所需要的执行次数是logN。
4、N^k:一半出现在k层循环嵌套中
三、常用的递推关系
1、斐波那契数列:Fn=Fn-1 + Fn-2;
2、Cn-C(n/2) = 1:对应二中的情况1:每次问题规模减半(如果对应3中的情形,相当于每次的运算规模或者说算法的输入减半,但是每次都要检查某个数据,结合二分法理解:二分法每次都要检查一个数字即可使得下一步的问题规模缩小);Cn=lgN
3、Cn-C(n/2) = n:每次的运算规模或者说算法的输入减半,但是每次都要检查所输入的数据;结果:Cn=n + n/2 + + n/4 + n/8+...(用累加法解答),化简后得到结果Cn=2n;
4、Cn-2C(n/2)=n:每次将问题的规模平均成两半,但是,每次都需要比较两个部分(平均分后的两个部分的数据)的每一个数据(可以结合快速排序的最好情形进行理解),这个其实是对应二中的情况3(此时n取2):每次平均为两份(相当于规模减半),但是呢,减半的两个部分都必须比较每个数据方可继续减半下去(递归下去)。(有点抽象,最好还是结合快速排序理解)
5、Cn-2Cn=1当4中的n为1(表示分半猴只需做常量级别的数据比较工作)时,对应结果为Cn=n
四、算法的其他概念
1、最好 or 平均 or 最坏:一般分析都是当成最坏情形,因为算法设计需要保守地考虑最坏情形;
2、递推公示的求解技巧
A、转化:一般会转化为等差、等比数列
B、变形技巧(以达到A的目的):有指数出现就取对数(一般会出现与2^n相关时);连加/乘推出关系;
(好吧,这些有点偏理论了,忽略吧!)