[算法技术]算法的时间复杂度

算法的时间复杂度是衡量一个算法效率的基本方法。在阅读其他算法教程书的时候,对于算法的时间复杂度的讲解不免有些生涩,难以理解。进而无法在实际应用中很好的对算法进行衡量。

《大话数据结构》一书在一开始也针对算法的时间复杂度进行了说明。这里的讲解就非常明确,言简意赅,很容易理解。下面通过《大话数据结构》阅读笔记的方式,通过原因该书的一些简单的例子和说明来解释一下算法的时间复杂度和它的计算方法。

首先从基本定义下手,来了解一下什么是“算法的时间复杂度”,《大话数据结构》一书中对算法的时间复杂度定义如下:

“算法语句总的执行次数 T(n) 是关于问题规模 n 的函数,进而分析 T(n) 随 n 的变化情况并确定 T(n) 的数量级。算法的时间复                杂度,也就是算法的时间度量,记作:T(n) = O(f(n)) 它表示随问题规模 n 的增大,算法执行时间的增长率和f(n) 的增长率                          相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中 f(n) 是问题规模 n 的某个函数。”

光从定义来理解算法的时间复杂度还是比较难的,我们再结合一个简单的例子来说明。计算 1 + 2 + 3 + 4 + ......  + 100 = ? 这样的问题想必大家都遇到过,这里我们通过 C 语言用最简单的方法实现一下这个问题的算法。

int sum = 0, n = 100;        //执行了 1 次

for (int i = 1; i <= n; i++) {        //执行了 n + 1 次

sum += i;        //执行了 n 次

}

printf(" sum = %d", sum);        //执行了 1 次

从代码附加的注释可以看到所有代码都执行了多少次。那么这写代码语句执行次数的总和就可以理解为是该算法计算出结果所需要的时间。所以说,上述结算 1 + 2 + 3 + 4 + ......  + 100 = ?的算法所用的时间(算法语句执行的总次数)为 :

1 + ( n + 1 ) + n + 1 = 2n + 3

而当 n 不断增大,比如我们这次所要计算的不是 1 + 2 + 3 + 4 + ......  + 100 = ? 而是 1 + 2 + 3 + 4 + ......  + n = ?其中 n 是一个十分大的数字,那么由此可见,上述算法的执行总次数(所需时间)会随着 n 的增大而增加,但是在 for 循环以外的语句并不受 n  的规模影响(永远都只执行一次)。所以我们可以将上述算法的执行总次数简单的记做:

2n 或者简记  n

这样我们就得到了我们设计的计算 1 + 2 + 3 + 4 + ......  + 100 = ?的算法的时间复杂度,我们把它记作:

O(n)

对于同一个问题,解法通常是不唯一的。比如 1 + 2 + 3 + 4 + ......  + 100 = ?这个问题,还有其他的不少算法。我们再来看一个数学家高斯解决这个问题的算法(想必大家都很熟悉这个故事)。

SUM = 1 + 2 + 3 + 4 + ......  + 100

SUM = 100 + 99 + 98 + 97 + ...... + 1

SUM + SUM = 2*SUM = 101 + 101 + 101 + .... + 101          正好 100 个 101

SUM =  (100*101)/2 = 5050

同样我们将这个解法翻译成 C 语言代码:

int n = 100, sum = 0;        //执行 1 次

sum = (n*(n + 1))/2;        //执行 1 次

printf("sum = %d", sum);        //执行 1 次

这样我们针对同一个 1 + 2 + 3 + 4 + ......  + 100 = ?问题,不同的算法又的到了一个算法的时间复杂度:

O(3)    一般记作 O(1) 我们后续给出原因。

从感官上我们就不难看出,从算法的效率上看,O(3) < O(n) 的,所以高斯的算法更快,更优秀(是最优秀的吗?)。

这种用个大写的 O 来代表算法的时间复杂度的记法有个专业的名字叫“大O阶”记法。那么通过对上述的例子进行总结,我们给出算法的时间复杂度(大O阶)的计算方法。

推导“大O阶”的步骤:

1、用常数 1 取代运行时间中的所有加法常数。

2、在修改后的运行次数函数中,只保留最高阶项。

3、如果最高阶项存在且不是 1 ,则去除与这个项相乘的常数。

下面我们在通过一个有不少 for 循环的例子按照上面给出的推导“大O阶”的方法来计算一下算法的时间复杂度。先看一下下面的这个例子的代码,也是用 C 语言写的,在注释上我们仍然对执行次数进行说明。

int n = 100000;        //执行了 1 次

for (int i = 0; i < n; i++) {        //执行了 n + 1 次

for (int j = 0; j < n; j++) {        //执行了 n*(n+1) 次

printf("i = %d, j = %d\n", i, j);        //执行了 n*n 次

}

}

for (int i = 0; i < n; i++) {        //执行了 n + 1 次

printf("i = %d", i);        //执行了 n 次

}

printf("Done");        //执行了 1 次

上面的代码严格的说不能称之为一个算法,毕竟它很“无聊而且莫名其妙”(毕竟算法是为了解决问题而设计的嘛),先不论这个“算法”能解决什么问题,我们看一下它的“大O阶”如何推导,还是先计算一下它的执行总次数:

执行总次数 = 1 + (n + 1) + n*(n + 1) + n*n + (n + 1) + 1 = 2n^2 + 3n + 3    这里 n^2 表示 n 的 2次方。

按照上面推导“大O阶”的步骤我们先来第一步:“用常数 1 取代运行时间中的所有加法常数”,则上面的算式变为:

执行总次数 = 2n^2 + 3n + 1    这里 n^2 表示 n 的2次方

第二步:“在修改后的运行次数函数中,只保留最高阶项”。这里的最高阶是 n 的二次方,所以算式变为:

执行总次数 = 2n^2    这里 n^2 表示 n 的2次方

第三步:“如果最高阶项存在且不是 1 ,则去除与这个项相乘的常数”。这里 n 的二次方不是 1 所以要去除这个项的相乘常数,算式变为:

执行总次数 = n^2    这里 n^2 表示 n 的2次方

因此最后我们得到上面那段代码的算法时间复杂度表示为: O( n^2 )        这里 n^2 表示 n 的2次方。

至此,我们对什么是“算法的时间复杂度”和“算法的时间复杂度”表示法“大O阶”的推导方法进行了简单的说明。当然要想在日后的实际工作中快速准确的推导出各种算法的“大O阶”我们还需要进行大量的联系,毕竟熟能生巧嘛。最后我们在把常见的算法时间复杂度以及他们在效率上的高低顺序记录在这里,是大家对算法的效率有个直观的认识。

O(1) 常数阶 < O(logn) 对数阶 < O(n) 线性阶 < O(nlogn) < O(n^2) 平方阶 < O(n^3) < { O(2^n) < O(n!) < O(n^n) }

最后三项我用大括号把他们括起来是想要告诉大家。如果日后大家设计的算法推导出的“大O阶”是大括号中的这几位,那么趁早放弃这个算法,在去研究新的算法出来吧。因为大括号中的这几位即便是在 n 的规模比较小的情况下仍然要耗费大量的时间,算法的时间复杂度大的离谱,基本上就是“不可用状态”。

当然了,还是要推荐一下《大话数据结构》这本书的。对于数据结构入门来说,这本书相当不错,很“生动活泼”,读起来也很有意思!

(0)

相关推荐

  • [算法技术]2 Egg Problem

    操作方法 01 2 Egg Problem 继续我们的推理问题之旅,今天我们要对付的是一个Google的面试题:Two Egg Problem. 我们开始吧! No.2  Google Intervi ...

  • 普利姆算法(prim)求最小生成树(MST)过程详解

    生活中最小生成树的应用十分广泛,比如:要连通n个城市需要n-1条边线路,那么怎么样建设才能使工程造价最小呢?可以把线路的造价看成权值求这几个城市的连通图的最小生成树.求最小造价的过程也就转化成求最小生 ...

  • 图解8大排序算法讲解

    排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 常见的内部排序算法有:插入排序.希尔排序. ...

  • 2017年了解百度SEO优化的7大算法

    搜索引擎发展至今,已公布了多种算法.作为 SEOER 的你,还不懂,就 out 啦.懂了不会用,也是然并卵的一种行为.了解算法知识并不懂得如何把算法实践于 SEO 工作的你,还是处于学生思维,是时候该 ...

  • 算法学习:什么是算法 (一)

    在编写计算机程序时,知道知种各样的算法有助于我们写出一个更"优雅"的程序.为了创造高效率.正确解决问题的程序,让我们开始学习吧. 操作方法 01 一.什么是算法? 算法就是解决问题 ...

  • 垃圾邮件过滤技术

    主要为邮件系统管理介绍几种常规的垃圾邮件过滤手段.通过专业的梭子鱼反垃圾邮件网关的设置不同的规则达到过滤垃圾邮件的效果. 操作方法 01 1.邮件发送认证 其实严格说起来,邮件发送认证技术是一种服务器 ...

  • 浏览器组成及工作原理深度了解

    简介 浏览器可以被认为是使用最广泛的软件,本文将介绍浏览器的工作原理,我们将看到,从你在地址栏输入google.com到你看到google主页过程中都发生了什么。 将讨论的浏览器 今天,有五种主流浏览 ...

  • 硬盘中SLC是什么及其优点.存取原理介绍

    储单元分为两类:SLC(Single Level Cell 单层单元)和MLC(Multi-Level Cell多层单元)。此外,SLC闪存的优点是复写次数高达100000次,比MLC闪存高10倍。此 ...

  • 真正的免费通话 触宝电话抢先体验评测

    下一个移动互联网的入口在哪里?毫无疑问通讯录成为大家瞄准的新目标。基于通讯录的移动产品已经开始发威,比如前段时间热门的秘密就是基于通讯录打通的移动互联体系,不过也别忘了通讯录最基本的作用——打电话。通 ...