在我参加的每次采访中,我都对复杂性的数学分析(包括big-O符号)进行了测验。
大O分析与行业发展之间的相关性如何?您真正使用它的频率是多少?对问题有一个稳定的思维定式是多么必要?
在我参加的每次采访中,我都对复杂性的数学分析(包括big-O符号)进行了测验。
大O分析与行业发展之间的相关性如何?您真正使用它的频率是多少?对问题有一个稳定的思维定式是多么必要?
Answers:
我的问题是,这种检验与工业发展有何关联?
对计算复杂性理论(例如,大O表示法)的扎实理解对于设计可伸缩算法,应用程序和系统至关重要。由于可伸缩性与行业中的计算高度相关,因此大的O符号也是如此。
您多久使用一次它,对问题有一个磨练的心态有多必要?
取决于您“实际使用它”的意思。一方面,我从未为所写软件做过计算复杂性的形式证明。另一方面,大多数日子里,我不得不处理可扩展性是潜在问题的应用程序,并且设计决策包括根据其复杂性特征选择(例如)适当的收集类型。
(我不知道如果不对复杂性理论有扎实的理解,是否有可能一致地实施可扩展系统。我倾向于认为事实并非如此。)
这样做的原因是因为它表示可伸缩性。
O(n ^ 2)的过程将比O(n log n)的过程更差,但比O(n ^ 3)甚至O(n!)的过程更好。
如果您不知道这些差异以及它们何时适用,则不适合选择正确的功能实现,以及将测试性能外推到生产性能中。
编辑:从http://www.codinghorror.com/blog/2007/09/everything-is-fast-for-small-n.html(又来自Programming Pearls)比较48n与n ^ 3
O(log Customers)
dB。
这取决于你在做什么。
对于Web开发人员(例如我),这通常很重要。您要扩展Web应用程序。如果您的应用程序有一个可以扩展为O(n ^ 2)的瓶颈,并且您认为这很好,因为您的服务器可以同时处理1000个用户,那么您似乎不需要在意。事实是,要处理两倍的数量(这很可能会在一夜之间发生),您将需要4倍的计算能力。理想情况下,您希望Web应用程序按O(n)进行扩展,因为硬件在合理的恒定用户/服务器比率下很便宜。
通常,在拥有10万个对象的应用程序中,大O会吃掉你。您极易受到高峰攻击。例如,我目前正在开发3D游戏,这是一个处理数据负载的应用程序。除了渲染外,您还需要进行碰撞检查,导航等操作。您需要高效的算法,需要大量的缓存,因此效率较低的算法会摊销。等等。
当然,如果您要做的是像通过在界面设计器中组合一个GUI来制作移动应用程序,然后将其与某些Web服务结合在一起,那么您永远不会遇到复杂性问题。因为您调用的Web服务已经解决了这一问题。
Big-O的性能很重要,但是已经被内部化了。
排序和搜索的Big-O性能无关紧要,因为人们通常使用系统提供的功能,并且这些功能将尽可能地好(假设它们通常需要有用)。有些数据结构对于不同的事物更有效,但是通常可以根据一般原则进行选择(并且通常内置于现代语言中)。有某种意义上的算法可扩展或不可扩展。
结果是形式问题很少在实践中出现,但是实践是建立在相同的原则上的。
恕我直言,许多计算机科学程序使许多学生在杂草丛中徘徊。这些程序从未完全传达出计算科学的全部内容。学生进入该行业,努力学习如何应用所学的概念,而对它们与现实世界的关系知之甚少。
我要说的是,计算科学的核心是推理能力。然后,您将学习各种方法和技术来执行此操作,并将其应用于抽象的问题,这些问题是在许多现实世界中发现的原型原型。诀窍是发现现实世界中的这些原型原语,然后推理诸如正确性,复杂性,时间等事物,您可能会同意,这是您需要担心的真实问题。深入了解各部分的行为方式,通常可以使您深入了解整体的行为方式。而且,相同的通用方法和技术也可以应用于整个过程,只是对较小的,抽象的,定义明确的部分所具有的严格性不相同。但最后,计算科学使您拥有合理的能力 决定如何安排计算,并真正了解计算在各种条件下的行为。
并不是的。基本上,我唯一想过的就是访问数据库。我通常会看一下代码,然后说“正在执行n + 1个查询,您应该将其更改为只执行1个或2个”
因为我的所有数据都是从数据库中读取并显示给用户,所以我尝试将正在处理的数据量减至最小,以至于线性算法与O(n ^ 2)算法之间的差异非常明显微不足道。
如果有问题,我们将在稍后进行分析和修复。
您提出了三个问题,我认为简短的答案可以帮助到目前为止给出的更长的论点。
该测试与行业发展之间的相关性如何?
取决于行业。
在代码速度或代码空间有问题的任何地方,它都与所涉及的行业完全相关。通常,您需要知道一个例程将花费多长时间,或需要多少内存(在线/离线)。
您多久使用一次?
取决于行业。
如果性能和扩展与手头的工作无关,那么只有在严重的性能不足的情况下,才很少。如果您是高度使用的关键系统的工程师,那么也许每天都可以。
对问题有一个磨练的心态是多么必要?
完全必要。
您可能每天都必须使用它,或者仅在严峻的情况下才使用它;但有时会需要。最好是在设计过程中,在问题到来之前,比拼命地分析扼流系统。
我会说这很频繁。我们通常不会证明某些东西具有特定的big-O,但我们已将其内在化,并记住/熟悉了特定数据结构和算法的big-O保证,并且我们为特定用途选择了最快的保证。拥有一个包含所有选项的库会很有帮助,例如Java集合库或C ++ STL。当您选择使用(查找)而不是(查找)并肯定选择不对(查找)进行线性搜索来查找不需要排序访问权限的内容时,您每天都会隐式地自然使用big-O 。java.util.HashMap
O(1)
java.util.TreeMap
O(lg n)
java.util.LinkedList
O(n)
当某人选择了次优的实现,并且知道更多的人出现并看到了他们的代码时,纠正它们是我们词汇的一部分:“您的实现花费了二次时间,但是我们可以做到这一点到n-log-n这种方式”与我们使用英语订购比萨一样自然而自然地自动进行。
除了交流思想外,我还没有发现它那么重要,并且我在性能至关重要的领域(光线跟踪,图像和网格处理,粒子系统,物理引擎等)工作,并且不得不设计出许多专有算法和数据结构在研发工作时。在这些领域中,通常只有少数几个非常高效的数据结构和算法可以产生全新的尖端产品,而昨天的算法却使现有产品过时了,因此人们总是追求使工作效率更高。需要说明的是,我从未发表过有关我设计的算法的论文。它们都是专有的。如果我这样做了,我将需要数学家的帮助来拟定证明等等。
但是在我看来,除非算法的伸缩性很差,否则每次迭代的计算工作量通常比算法的可伸缩性更重要。如果有人提出了一种先进的射线追踪技术,那么我对计算技术(例如它们如何表示和访问数据)比算法复杂性更感兴趣,因为在这种竞争性和创新性的场景中已经有了合理的可伸缩性。提出无法扩展的算法将无能为力。
当然,如果您要比较二次复杂度和线性运算,那是一个巨大的差异。但是我领域的大多数人都有能力避免在史诗输入上应用二次复杂度算法。因此,可扩展性通常被深深地暗示着,更有意义和更有趣的问题变成:“您是否使用过GPGPU?SIMD?它是否并行运行?您如何表示数据?您是否针对高速缓存友好的访问模式重新组织了它?如何它需要多少内存?它能可靠地处理这种情况吗?您要推迟某些处理还是一次完成?”
如果前者以更优化的模式访问内存,甚至更适合于多线程和/或SIMD,则即使是线性算法也可以胜过线性时间算法。有时,由于这些原因,即使是线性算法也可以胜过对数算法,而对于小输入,线性时间算法自然也胜过对数算法。
因此,对我而言,更重要的是某些人可能称为“微优化”,例如数据表示(内存布局,具有热/冷字段拆分的访问模式等),多线程,SIMD,有时还包括GPGPU。在一个领域里,每个人都已经有足够的能力去使用像样的尖端算法来处理所有问题,并且新论文一直在发表,在击败算法向导方面的竞争优势并不是来自算法复杂性的提高,而是来自更直接的计算效率。
我的领域是由杰出的数学家主导的,但并非总是知道他们正在做的计算成本或许多加快代码速度的较低技巧的人。尽管我的复杂程度不高,但在设计更快,更紧凑的算法和数据结构时,通常这是我的优势。我正在尝试硬件喜欢的东西,朝着比特和字节的方向努力,即使我比真正复杂的算法做更多的工作迭代,也使每次迭代的工作便宜得多-在我的情况下,工作便宜得多。我编写的代码也往往更简单。如果人们认为难以直接理解算法和数据结构的微观优化版本,就很难理解和维护,
作为一个基本示例,我想出了一个简单的网格结构,该结构最终在我们公司的KD树中表现出优于碰撞检测和冗余点去除的性能。我愚蠢的原始网格在算法上没有那么复杂,在数学上和算法上都比用他的KD-tree以新颖的方式找到中点的家伙笨拙,但是我只是调整了网格的内存使用和访问模式,这足以胜过更复杂的东西。
我所拥有的另一个优势,使我能够在一个比我聪明得多的人所统治的领域中生存,只是真正地了解用户的工作方式,因为我使用软件的开发方式相同。这给了我一些算法的想法,这些算法实际上非常符合用户的兴趣。作为一个基本示例,大多数人都尝试使用空间索引来加速诸如碰撞检测之类的事情。我在大约几十年前就对有机模型进行过一次简单的职业塑造观察,例如,如果角色将手放在脸上,则空间索引结构将需要拆分节点并进行昂贵的更新(如果角色)然后将手从脸上移开。相反,如果您根据连通性数据而不是顶点位置进行分区,您可以得到一个稳定的层次结构,该结构可以非常快速地更新,并且不需要拆分或重新平衡树(只需要在动画的每个帧中更新边界框)...像这样的事情-算法不需要笨重的数学背景如果他们只是了解基本概念,就可以提出来,但是由于他们没有以如此接近用户工作方式的方式来思考事物,并且对几何的特性而不是对几何的思考太多,从而使数学家们望而却步被普遍使用。与算法巫师相比,我更多地依靠一般的计算知识和用户端知识来相处得很好。因此,无论如何,我并没有发现专注于算法复杂性那么重要。
采访中提出的问题可以找出你是否可以解释事物并以逻辑方式思考。面试官还试图找出您是否可以运用您所知道的知识来解决相关问题。
每个对软件工程进行了有价值研究的人都会遇到“ Big O”的问题,要回答有关“ Big O”的好问题,您还必须对标准数据结构和算法有所了解。
在为员工进行面试时,您正在寻找的是可以快速学习工作的人,而不是已经知道一组给定详细技能的人,因此很难选择面试官和被访方都具有共同理解的问题的。
因此,有关“大O”的问题可能与面试过程非常相关。
至少在我作为计算机程序员的漫长岁月中,由于某些人不了解要使用的正确数据结构和算法,我不得不修复缓慢的代码,但是您可以在不了解Big O的情况下解决这些问题。但是,确实了解大帐篷的人并没有首先避免这些问题。