算法问题是软件工程面试事实上的标准:谷歌、Facebook和许多其他公司都在使用它们。很难说这是否是进行技术面试的最佳方式,但算法思维对于软件工程师来说是一项宝贵的技能。这是众所周知的事实,但对事物有直觉总是好的,而不仅仅是事实的知识。在关于玩具金字塔的故事中,有一个有趣的时刻,主角被赋予了组装尽可能高的金字塔的任务。一个从小到大的项目的玩具故事主角很简单:从一个积木开始,然后在第一个积木之后再放置三个积木,在其上放置另一个积木,并继续以类似的时尚水平添加新积木。我们使用一个循环公式来计算达到一个新级别需要多少块/时间:N(level)=level*2+1+N(level-1)这个公式基本上遵循构建过程,执行这个的代码计算如下所示:funccountBlocks(levelint)int{if(level==0){return1;}returnlevel*2+1+countBlocks(level-1)}平凡的递归函数。然而,这段代码并不是最优的:每个新的方法调用都需要在调用堆栈中有一个新的条目,这会占用一些空间。在我们的例子中,我们有一个递归,但这是一种称为“尾递归”的特殊情况,可以用for循环代替。如果有人想计算1,000,000的值,基于循环的代码会执行(除非int可能溢出),而基于递归的版本可能会耗尽内存。重构后的代码如下所示:funccountBlocks(finalLevelint)int{seconds:=1//startingwithMVPforl:=0;l<最终等级;l++{seconds+=(finalLevel-l)*2+1}returnseconds}我们从第0层开始,计算该层所需的块数,然后进入下一层,直到到达最后一层。这是非常有道理的。然而,这个解决方案也不是最优的。如果我们重新审视我们的问题,我们可能会得出一个最优解。我们会做什么?我们需要计算需要多少块才能将金字塔添加一层。到目前为止,我们已经开发出一种方法来计算放置在金字塔顶部的块数,从而为金字塔添加一个级别。但是,如果我们不在金字塔顶部添加块,而是构建一个新的底层呢?那么要算出需要多少块就没那么容易了:底是一个正方形,正方形的面积就是正方形的边的平方!因此,最优解是:funccountBlocks(levelint)int{side:=level+1//Sincewestartwithlevel0returnside*side}这个解是帕累托最优的:它更简洁,更高效,更不容易发生错误。我们的第一个优化很好,但要获得最佳解决方案,我们必须评估如何获得答案,而不是如何最好地优化现有方法。为了获得最佳解决方案,我们首先提出问题并以某种方式获得EricEvans所说的突破-一种在解决方案是简单方法时查看所述问题的方式。是的,我们可以通过计算应该添加到现有级别的所有块来得到答案,但是当我们只计算构建下一个底层级别所需的块数时,这种解决方案不必要地复杂。达到突破的时刻更像是一门艺术,但了解计算机科学的发现可能会非常有帮助。幸运的是,最好的大学提供包括以下材料的在线课程:TimRoughgarden的(斯坦福大学)算法专业化——一门很好的深度课程,完全侧重于具有挑战性的作业的算法(使用任何编程语言来完成作业)·算法第1部分和RobertSedgwick(普林斯顿大学)的第2部分-也是一门具有困难任务的深入课程,但侧重于算法及其在Java中的实现。(本文翻译自YanBabitski的文章《The power of algorithms》,参考:https://medium.com/@yan.babit...
