时间复杂度与空间复杂度
一般算法都可以转化成一个数学方程,表示的是一个时间复杂度之和,而我们为了方便表达,会把对于影响比较小的式子省略掉,去掉不会变的常数,只留下一个对于复杂度影响最大的函数
正文
对于一个给定的算法,第一是从数学上证明算法的正确性,这一步主要用到形式化证明的方法及相关推理模式,如循环不变式
、数学归纳法
等。
第二就是分析算法的时间复杂度,算法的时间复杂度反应了程序执行时间随输入规模增长而增长的量级,在很大程度上能很好反应出算法的优劣
算法执行时间需要通过依据该算法编制的程序在计算机上运行所消耗的时间来度量,通常有两种办法
一、事后统计法
就是统计算法在机器上运行时间
有两个缺陷:
1. 要想对设计的算法的运行性能进行评测,必须先依据算法编制相应的程序并实际运行
2. 所得时间的统计量依赖于计算机的硬件、软件等环境因素,有时容易掩盖算法本身的优势
二、事前分析估算法
最常采用的方法
在编写程序前,依据统计方法对算法进行估算。一个用高级语言编写的程序在计算机上运行时所消耗的时间取决于下列因素:
1. 算法采用的策略
2. 编译产生的代码质量
3. 问题的输入规模
4. 机器执行指令的速度
一个算法shi是由控制结构(顺序分支循环)和原操作(指固有数据类型的操作)构成的,则算法时间取决于两者的综合效果。为了便于比较同一个问题的不同算法,通常的做法是,从算法中选取一种对于所研究的问题(或算法类型)来说是基本操作的原操作,以该基本操作的重复执行的次数作为算法的时间量度
时间复杂度
1. 时间频度
一个算法花费的时间与算法中语句的执行次数成正比例。那个语句执行次数多,花费时间就多。一个算法中的语句执行次数称之为语句频度或时间频度,记为 T(n)。
2. 时间复杂度
在时间频度中,n称为问题的规模,当n 不断变化时,时间频度 T(n) 也会不断变化。
一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用 T(n) 表示,若有某个辅助函数 f(n),使得当 n 趋于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称 f(n )是同数量级函数。 记作 T(n) = O(f(n))称O(f(n))为算法的渐进时间复杂度,简称时间复杂度
注:Landau符号(O)的作用在于用简单的函数来描述复杂函数行为,给出一个上或下(确)界
在各种不同算法中,若算法中语句执行次数为一个常数,则时间复杂度为O(1),另外,在时间频度不相同时,时间复杂度有可能相同,如T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。 按数量级递增排列,常见的时间复杂度有:常数阶O(1),对数阶O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),…, k次方阶O(nk),指数阶O(2n)。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
3. 求算法的时间复杂度的具体步骤
- 找出算法中的基本语句
- 算法中执行次数最多的那条语句激素hi基本语句,通常是最内层循环的循环体
- 计算基本语句的执行次数的数量级
- 只需计算基本语句执行次数的数量级,这就意味着只要保证基本语句执行次数的函数中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数,这样能够简化算法分析,并且使注意力集中在最重要的一点上:增长率。
- 用大 O 记号表示算法的时间性能
O(1) 表示基本语句的执行次数是一个常数,一般来说,只要算法中不存在循环语句,其时间复杂度就是 O(1)。其中Ο(log2n)、Ο(n)、 Ο(nlog2n)、Ο(n2)和Ο(n3)称为多项式时间,而Ο(2n)和Ο(n!)称为指数时间。计算机科学家普遍认为前者(即多项式时间复杂度的算法)是有效算法,把这类问题称为P(Polynomial,多项式)类问题,而把后者(即指数时间复杂度的算法)称为NP(Non-Deterministic Polynomial, 非确定多项式)问题。
4. 简单程序分析法则
(1).对于一些简单的输入输出语句或赋值语句,近似认为需要O(1)时间
(2).对于顺序结构,需要依次执行一系列语句所用的时间可采用大O下”求和法则”
求和法则:是指若算法的2个部分时间复杂度分别为 T1(n)=O(f(n))和 T2(n)=O(g(n)),则 T1(n)+T2(n)=O(max(f(n), g(n)))
特别地,若T1(m)=O(f(m)), T2(n)=O(g(n)),则 T1(m)+T2(n)=O(f(m) + g(n))
(3).对于选择结构,如if语句,它的主要时间耗费是在执行then字句或else字句所用的时间,需注意的是检验条件也需要O(1)时间
(4).对于循环结构,循环语句的运行时间主要体现在多次迭代中执行循环体以及检验循环条件的时间耗费,一般可用大O下”乘法法则”
乘法法则: 是指若算法的2个部分时间复杂度分别为 T1(n)=O(f(n))和 T2(n)=O(g(n)),则 T1*T2=O(f(n)*g(n))
(5).对于复杂的算法,可以将它分成几个容易估算的部分,然后利用求和法则和乘法法则技术整个算法的时间复杂度
另外还有以下2个运算法则:(1) 若g(n)=O(f(n)),则O(f(n))+ O(g(n))= O(f(n));(2) O(Cf(n)) = O(f(n)),其中C是一个正常数