频 道 直 达 - 新闻 - 培训 - 软件 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 读书 - 博客 - BBS
51CTO.COM_中国最大的网络技术网站
找资料:

3.3 分析解决方案

作者: John Mongan等著,王海鹏译 出处:机械工业出版社华章公司  2008-02-20 13:57    砖    好    评论   进入论坛
阅读提示:《程序员面试攻略》提供了50个面试场景,并且深入分析了各种解决方案。第三章主要讲的是编程问题的解答思路,本小节为分析解决方案。

3.3   分析解决方案

当您回答了问题之后,面试考官可能会问您实现的效率。通常,您需要将您的实现与其他可能的解决方案进行比较,说明各种方案的折衷考虑,并说明每一种解决方案最适合的情况。常见的问题是关于内存或空间的使用,特别是如果使用了递归的话。

深刻理解时间复杂度分析将给面试考官留下深刻的印象。时间复杂度分析是一种运行时间的分析,用于测量算法在时间方面的效率,即运行的时间与输入的规模之间的函数关系。它不是正式的基准测试,只是确定算法的效率的一种简便的方法。

本书中包含的大多数编码问题解决方案都带有运行时间分析,帮助您强化对算法的理解。

分析两个例子 让我们从一个时间复杂度分析的例子开始。请考虑一个简单的函数,它返回一个非负数组中存放的最大值。数组的大小为n。

至少有两种容易的方法来实现这个函数。在第一种方法中,您在函数遍历数据的过程中记住当前最大的值,在完成遍历时返回该值。我们把这种实现取名为“CompareToMax”,它看起来是这样的: 第二种方法将每一个值与所有其他的值进行比较。如果所有其他的值都小于或等于该值,那它就是最大的值。我们把这种实现取名为“CompareToAll”,它看起来是这样的。

这两个函数都能正确地返回最大值。哪一个更有效率?您可以试着运行基准测试,但对每一种可能的方式进行基准测试是不现实的(也是无效率的)。您需要在实现算法之前就能够预测它的性能。时间复杂度分析让您能够做到这一点:比较并预期不同算法的性能。

时间复杂度分析为何有效 在时间复杂度分析中,输入的规模假定是n。在这个例子中,n就代表数组中元素的个数。在其他问题中,n可能代表链表的结点数、一个数据类型的位数、或哈希表中的项数等。在弄明白n对于您的输入来说是什么含义之后,必须确定这n个输入项被检查了多少次。“检查”是一种泛指,因为对于不同的算法来说,操作是不同的。一般来说,检查可能是将输入值加到一个变量中,创建新的输入项,或删除输入值。在时间复杂度分析中,这些操作被认为是等价的。在CompareToMax和Compare ToAll中,“检查”意味着将数组的一个值与另一个值进行比较。

在CompareToMax中,每个数组元素都与最大值比较一次。因此,这n个输入项每个都会被检查一次,结果是进行了n次检查。这可以记作O(n),通常称为“线性运时间”:运行算法所需的时间随着输入项个数的增加呈线性增长。 您可能注意到,除了对每个元素检查一次之外,还有一次确保数组不为空的检查,以及一个初始化curMax变量的步骤。似乎O(n + 2)更能准确地反映这些额外的操作。但是时间复杂度分析反应的是渐近的运行时间,即当n变得非常大时运行时间的极限。因为n趋向于无穷大,n和n + 2之间的差别就不重要了,类似地,对于运行n + n2次的算法,当n变得很大时,n2和n + n2之间的差别是可以忽略的。因此,在时间复杂度分析中,您只要留下最高幂次项,即当n变得非常大时最大的那一项。因此,CompareToMax的时间复杂度是O(n)。

CompareToAll的分析要更难一些。首先,您必须假定最大的数字出现在数组的什么位置。现在,假定最大的元素出现在数组的末尾。在这种情况下,每个元素都与其他n个元素进行比较。因此有n×n次检查,它是时间复杂度为O(n2)的算法。 前面的分析研究表明,CompareToMax的时间复杂度是O(n),CompareToAll的时间复杂度是O(n2)。这就是说,当数组增长时,CompareToAll的比较次数要比CompareToMax的比较次数大很多。假定数组有30 000个元素,CompareToMax的比较次数的规模在30 000次,而CompareToAll的比较次数规模在900 000 000次。您可以预计CompareToMax要快很多,因为它要快30 000倍。实际上,一次CompareToMax的基准测试时间是0.01秒,而CompareToAll的时间是23.99秒。

时间复杂度分析中最快的结果是O(1),通常称为“常数运行时间”。不论输入的规模是多少,对于具有常数运行时间的算法来说,其执行时间总是一样的。

最好情况、平均情况和最坏情况

您可能认为这种比较对于CompareToAll来说是不公平的,因为最大值是在最后出现的。确实如此,这提出了一个重要问题,即运行时间的最好情况、平均情况和最坏情况。对CompareToAll的分析是最坏的情况:最大值在数组的末尾。但请考虑平均情况,最大值在中间。检索结束时,只检查了n/2次,因为最大值位于中间。这会导致n(n/2) = n2/2次检查。这似乎得到了复杂度为O(n2/2) 的运行时间。但是请考虑1/2这个因数的意义。检查每个值的实际时间基本上取决于代码翻译成的指令,以及CPU执行这些指令的时间。因此1/2也没有太大的意义。甚至可能会遇到O(n2)的算法执行得比O(n2/2)的算法要快。在时间复杂度分析中,您可以将所有的常数因子去掉,因此CompareToAll的平均情况比最坏情况也好不了多少,仍是O(n2)。

CompareToAll的最好情况要比O(n2)好。在这种情况下,最大值在数组开始处。最大值仅与其他值进行一次比较,所以结果是O(n)。

请注意,在CompareToMax中,最好情况、平均情况和最坏情况是一样的。不论数组中的值如何排列,算法的时间复杂度总是O(n)。

请向面试考官询问他们最感兴趣的场景是什么。有时候问题本身就包含了一些线索。有些排序算法对于无序的数据的时间复杂度很差,但对于差不多排好序的数据却很适合。

如何进行时间复杂度分析

进行时间复杂度分析的一般过程如下:

1. 弄清楚输入是什么以及n代表什么。
2. 用n来表示该算法执行的操作的次数。
3. 仅保留最高幂次的项。
4. 去掉所有的常数因子。

对于您遇到的测试算法,只要您正确地确定了与输入规模相关的操作,时间复杂度分析应该很简单。

优化与时间复杂度分析

算法优化并不一定会带来总体运行时间的预期变化。请考虑对CompareToAll进行下面的优化:不是将每个数字与其他数进行比较,而是将每个数字与数组中排在它后面的数字进行比较。实质上,排在当前数字之前的数字已经与当前数字比较过了。因此,如果只将当前数字与它之后的数字进行比较,这个算法仍然是正确的。

对于这个实现,最坏的情况是怎样的?第一个数字与n个数字进行了比较,第二个数字与n-1个数字进行了比较,所以总的比较次数是n + (n - 1) + (n - 2) + (n - 3) + … + 1。这是一个很普通的结果,这个数列的结果可以表示为n2/2 + n/2。n2是最高幂次的项,所以这个版本的算法的时间复杂度在最坏的情况下仍然是O(n2)。对于输入值很大的情况,您对算法所做的改动对运行时间没有产生实质性的影响。

【责任编辑:雪花 TEL:(010)68476606】

回书目   上一节   下一节
专题
程序员如何成长?
程序员面试攻略 第2版
微软出价446亿美元收购雅虎
Use Case入门与实例
UML嵌入式设计
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 最 大 的 网 络 技 术 网 站 ·
技 术 成 就 梦 想
订阅技术快讯
电子杂志下载
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。
名称:Vista精品应用黄皮书
简介:《Vista精品应用黄皮书》囊括了Vista的各方面内容。此次的精简版,是将里面的内容做了提取,便于用户下载和使用。内容包含了各种Vista的安装与实施、技巧与解析以及各种Vista相关学习文档和相关软件的安全下载。该电子书是了解和应用Vista人员必备的工具手册,并且也是第一本