算法分析
算法还是CS的最最基础也是最组重要的东西,想去面试大厂的AI岗,基本重点考察的都是算法的东西,甚至可能会现场手撕算法。所以,算法的学习是不能停止的,要时刻保持学习和刷题的状态。
对同一类问题可以有多种不同的解决方法,比如排序算法就分为好多种排序方法,比较常见的是8种排序算法(后期博客会讲到并通过代码实现)。而一个算法的质量优劣可以影响到算法乃至程序的效率,我们就来想办法改进算法,提高程序执行的效率。
算法分析的目的在于改进算法,那么首先的问题是如何对算法进行评价呢?
首先第一个前提是,算法必须是正确的。所谓一个正确的算法是指,当输入一组合理的数据时,能够在有限的运行时间内得到正确的结果;对于不合理的数据输入,能够给出警告提示信息(明确定义:对于不合理的数据输入的反应能力和处理能力,通常称为算法的健壮性)。
第二,还应考虑以下的3个方面:
1.一句算法编写的程序在计算机中运行时间的多少的度量,即通常所说的时间复杂度。
2.依据该算法编写的程序占用计算机存储空间多少的量度,即空间复杂度。
3.其他方面,如算法的可读性,简洁性,可移植性以及易测量性的好坏来进行评判。
这里的时间复杂度和空间复杂度并不是绝对的空间和时间多少的概念,而是一个数量级的概念,在更多的时候,时间和空间是相对制约的,算法在时间和空间上的开销往往是矛盾的,十全十美的算法很少。有时候,形式上很简单的算法运行时间可能比形式上复杂的算法的运行时间长的多;一个运行时间很少的程序可能占用的存储空间很大。
有时,为了取得较好的时间效率目的,甚至不惜以牺牲空间为代价
时间复杂度
影响运行时间多少的因素有以下:
1.问题的规模,或问题的数量级
2.源程序的编译功能的强弱以及经过编译之后产生的机器代码质量的优劣
3.机器执行一条指令的时间长短
4.程序中语句的执行次数
但是,对于不同的计算机或者不同的操作系统来说,可能出现不同的结果,这表明使用绝对时间来度量算法的时间效率是不合适的。因此,我们通常的做法是将算法中的语句执行次数作为算法时间多少的度量。
这种把语句执行次数的多少作为算法时间复杂度的度量分析方法叫做频度统计法。
在最坏的情况下,如果存在一个增长上限,ng(n),则该算法的时间复杂度增长的数量级为g(n),即算法的渐进时间复杂度为O(g(n))。[通常用数量级来表示]
算法的时间复杂度通常有一下几种:
O(1),O(n),O(n^ 2),O(n^ 3),O(logn),O(nlogn),O(2^n)等几种形式。
当n增长到一定的程度后,各种不同的数量级所对应的值存在如下关系:
我们通常用大O表示方法来描述,
大O表示的加法规则是f(m, n)=f1(n) + f2(m)=O(max(g1(n), g2(m)))
大O表示的乘法规则是f(n, m)=f1(n) * f2(m)=O(g1(n) * g2(m))
其中,O(1)表示算法的时间复杂度为常量,不随问题规模n的大小而变化;
具有O(n)数量级的算法被称为线性算法,运行时间与n成正比,如长度为n的线性表中采用顺序查找的方法进行查找时,时间复杂度为O(n);
时间复杂度为O(logn)的算法的运行时间与n的对数成正比,如具有n个记录的排序连续文件中采用折半查找法进行查找时的算法就是这样。
空间复杂度
算法在计算机上占用的空间包括3方面:
1.存储算法本社占用的空间、
2.算法的输入输出数据所占用的空间、
3.算法在运行过程中临时占用的空间。
1.存储算法本社占用的空间与算法书写的长度成正比,要压缩算法长度,就必须编写出精炼的算法;
2.算法的输入输出数据所占用的空间是由解决的问题决定的,不随算法的不同而改变。
3.算法在运行过程中临时占用的空间因算法而异,有的算法只需要占用少量的临时工作单元而不随问题规模的大小而改变;有的算法需要占用大量的临时工作单元的数目则随着问题规模的增大而增大,当问题的规模较大时,算法将占用较大的临时空间。
分析一个算法的空间复杂度要综合多方面因素进行。对于递归算法来说,在形式上一般都比较短,本身占用的存储空间并不多,但算法在运行过程中,需要设置一个附加堆栈,从而占用了较多的临时工作单元。不能仅仅看其算法本身代码长度就判断其空间复杂度。
计算算法的空间复杂度是比较容易的,包括局部变量所占用的存储空间(算法范围内定义的变量)和系统为实现递归所占用的堆栈空间(如果是递归算法的话)两部分,通常空间复杂度也以数量级O(n)的形式给出。
上一篇: 算法分析
下一篇: Docker Compose入门