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)。对于输入值很大的情况,您对算法所做的改动对运行时间没有产生实质性的影响。
| 回书目 上一节 下一节 |
|
· C语言之基础自测获奖名.. · Linux服务器架设自测获.. · 边界网关安全防护自测.. · Cisco CCNA最新真题自.. · 我在美联储监管银行 书.. · 我在美联储监管银行 目.. |
· 我在美联储监管银行 前.. · 入侵的艺术 目录 · 入侵的艺术 前言 · 网管员全真面试题自测.. · 子弹的本质—— 形势没.. · 学习大量的词汇—— 对.. |
|
||||
| · Windows Server 2008 · SQL Server 2008/2005.. · 打造安全网络环境 · 网络安全产品检验规范 · 华为、贝恩资本22亿美.. · 社会工程学与网络安全 · 离职员工安全隐患 · 杀毒软件评测专题 |
· Sun以10亿美元并购开源.. · 中间件应用技术专题 · 杀毒软件优化和使用技巧 · 信息安全等级保护专题 · 补丁自动分发管理策略.. · 杀毒王牌 · AMD Phenom三核处理器.. · 国际文档格式标准开战 |
|||
|
||||
| · VPN技术 · SQL Server 2008/2005.. · SOA 面向服务架构 · 子网掩码教程 · SQL Server 2008/2005.. · 中间件应用技术专题 · 深入了解PGP加密技术 · MySQL数据库备份 |
· 病毒查杀专题 · VPN技术 · Solaris 10 配置管理 · Linux 基础 · SSL VPN详细知识 · Linux防火墙 · 路由器设置与口令恢复 · Linux 集群技术专题 |
|||
|
||||
| · VPN技术 · SQL Server 2008/2005.. · 中间件应用技术专题 · SQL Server 2008/2005.. · SOA 面向服务架构 · 子网掩码教程 · MySQL数据库备份 · 身份认证技术 |
· 病毒查杀专题 · 清除流氓软件——51CTO.. · SSL VPN详细知识 · Sniffer安全技术从入门.. · 常用交换机典型配置 · 路由器设置与口令恢复 · Linux 集群技术专题 · VPN技术 |
|||