算法复杂度简述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhchs2012/article/details/79716992

零、前言

在我本科参与ACM院队培训时,来自校队的学长就给我们讲过复杂度的概念,可惜当时年轻不懂事,没有好好消化,现在来补补课。

一、时间复杂度

1.1 时间频度

一个算法花费的时间与算法中语句的执行次数成正比。算法中语句的执行次数称为语句频度或时间频度。记为T(n)。
这个概念了解即可,抄自百科,不是重点。

1.2 时间复杂度

在T(n)中,n称为问题的规模,n不同,T(n)自然也不同。一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数。这里的n可以理解为某个入参数组的长度,或者某个矩阵的元素个数。
设定一个T(n)的同数量级函数f(n),当n趋近于无穷大时,T(n)/f(n)的极限为一个常数。记T(n) = O(f(n))为算法的渐进时间复杂度,简称时间复杂度。
补充:其实复杂度的符号现在我们基本只能看到大写字母O,在《算法导论》中Big-O整个family都有介绍,包括O,Θ,Ω。本来都是希腊字母,大家为了打起来方便都用了英文字母O,打起来方便对程序员来说真的是很重要的一点,再加上不是数学系的人不见得对数学符号有很深的执念,差不多得了。这几个符号之间的差距解释起来还蛮繁琐的,当前我也没把握说清楚,就先跳过吧。见谅见谅
用O(n)来体现算法时间复杂度的记法被称作大O表示法。

1.3 时间复杂度计算方法

一般我们评估一个算法都是直接评估它的最坏情况下的复杂度。
大O表示法O(f(n))中的f(n)的值可以为1、n、logn、n^2 等,所以我们将O(1)、O(n)、O(logn)、O( n^2 )分别称为常数阶、线性阶、对数阶和平方阶。
常见的时间复杂度由小到大依次为:Ο(1)<Ο(logn)<Ο(n)<Ο(nlogn)<Ο(n^2)<Ο(n^3)<…<Ο(2^n)<Ο(n!)
所以,我们应该尽可能地选用多项式阶O(n^k)复杂度的算法,指数阶和阶乘阶使我们不希望看到的,因为开销实在太大。

1.3.1大O表示法三规则

  1. 用常数1取代运行时间中的所有加法常数
  2. 只保留最高阶项
  3. 去除最高阶的常数

1.3.2具体步骤

1.找出算法中的基本语句;

算法中执行次数最多的那条语句就是基本语句,通常是最内层循环的循环体。

2.计算基本语句的执行次数的数量级;

只需计算基本语句执行次数的数量级,这就意味着只要保证基本语句执行次数的函数中的最高次幂正确即可,可以忽略所有低次幂和最高次幂的系数。

3.用大Ο记号表示算法的时间性能。

将基本语句执行次数的数量级放入大Ο记号中。如果算法中包含嵌套的循环,则基本语句通常是最内层的循环体,如果算法中包含并列的循环,则将并列循环的时间复杂度相加。

1.4时间复杂度计算小结


  1. 对于一些简单的输入输出语句或赋值语句,认为需要O(1)时间;
  2. 对于顺序结构,需要依次执行一系列语句所用的时间可采用大O下”求和法则”;
  3. 对于选择结构,如if语句,它的主要时间耗费是在执行then字句或else字句所用的时间,需注意的是检验条件也需要O(1)时间;
  4. 对于循环结构,循环语句的运行时间主要体现在多次迭代中执行循环体以及检验循环条件的时间耗费,一般可用大O下”乘法法则”;
  5. 对于复杂的算法,可以将它分成几个容易估算的部分,然后利用求和法则和乘法法则计算整个算法的时间复杂度。

求和法则:是指若算法的2个部分时间复杂度分别为 T1(n)=O(f(n))和 T2(n)=O(g(n)),则 T1(n)+T2(n)=O(max(f(n), g(n))),用于顺序结构;
乘法法则:是指若算法的2个部分时间复杂度分别为 T1(n)=O(f(n))和 T2(n)=O(g(n)),则 T1*T2=O(f(n)*g(n)),用于循环嵌套结构。

1.5时间复杂度总结

一般来说,只要算法中不存在循环语句,其时间复杂度就是Ο(1)。其中Ο(logn)、Ο(n)、 Ο(nlogn)、Ο(n2)和Ο(n3)称为多项式时间,而Ο(2n)和Ο(n!)称为指数时间。计算机科学家普遍认为前者(即多项式时间复杂度的算法)是有效算法,把这类问题称为P(Polynomial,多项式)类问题,而把后者(即指数时间复杂度的算法)称为NP(Non-Deterministic Polynomial,,非确定多项式)问题。

二、空间复杂度

类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的度量。一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。

三、后话

一般我们在聊复杂度的时候,都默认是时间复杂度。这两个复杂度是往往是相互影响的。更小的时间复杂度可能会占用更多空间;反之,追求更少的空间复杂度,可能会占用更长的运行时间。很多时候我们都用空间来换取时间,可能原因是现在的存储设备相对于计算机的算力更便宜吧。另一方面,时效性也是很多程序需要考虑更重要的问题。

猜你喜欢

转载自blog.csdn.net/zhchs2012/article/details/79716992