我在大学里分配了一个练习。我把它带回家并尝试编写一种算法来解决它,我想这与图有关,可以找到连接的组件。
然后,我想到了最琐碎的事情,然后告诉我的讲师。经过简短的观察,他认为我的解决方案的运行时复杂性是不可行的,并显示出一些更有效的方法。而且有一种传统的程序员不知道什么是计算复杂性(我就是其中之一),所以如果程序员不知道什么是计算复杂性会存在问题吗?
我在大学里分配了一个练习。我把它带回家并尝试编写一种算法来解决它,我想这与图有关,可以找到连接的组件。
然后,我想到了最琐碎的事情,然后告诉我的讲师。经过简短的观察,他认为我的解决方案的运行时复杂性是不可行的,并显示出一些更有效的方法。而且有一种传统的程序员不知道什么是计算复杂性(我就是其中之一),所以如果程序员不知道什么是计算复杂性会存在问题吗?
Answers:
是的,我想说的是,对于任何认真的程序员来说,都必须了解计算复杂性。只要您不处理庞大的数据集,您就不会知道复杂性就可以了,但是如果您想编写一个解决严重问题的程序,则需要它。
在您的特定情况下,查找连接组件的示例可能适用于多达节点的图形。但是,如果您尝试使用具有节点的图,那么讲师的算法可能会在1秒钟内完成管理,而您的算法(取决于复杂性的程度)将花费1小时,1天甚至是1个永恒。
学生在我们的算法课程中犯的一个常见错误是遍历如下数组:
while array not empty
examine first element of array
remove first element from array
这可能不是最漂亮的代码,但是在复杂的程序中,可能会出现这样的情况,而程序员不会意识到这一点。现在,这个程序有什么问题?
假设我们在元素的数据集上运行它。与以下程序相比,前一个程序的运行速度要慢。
while array not empty
examine last element of array
remove last element from array
我希望您同意,对于程序员来说,拥有使程序运行速度快倍的知识可能是一件重要的事情。要了解这两个程序之间的差异,就需要一些有关复杂性理论的基础知识,以及一些有关要使用的编程语言的知识。
用我的伪代码语言,“从数组中删除元素”会将所有元素向右移,而要删除的元素则从左侧移至一个位置。这使得删除最后一个元素成为操作,因为要做到这一点,我们只需要与1个元素进行交互即可。删除第一个元素是因为要删除第一个元素,我们需要将所有其他元素也向左移动一个位置。
一个非常复杂的基本练习是证明第一个程序将执行操作,而第二个程序仅使用操作。如果您插入您将看到一个程序比另一个程序效率更高。
这只是一个玩具示例,但是已经需要对复杂性有基本的了解,才能分辨出这两个程序之间的区别,如果您实际上是在尝试调试/优化有此错误的更复杂的程序,则需要更深入的了解才能找到找出错误所在。因为类似这样的错误可以通过代码中的抽象很好地隐藏,以这种方式从数组中删除元素。
在比较两种解决问题的方法时,对复杂性有很好的了解也将有所帮助。假设您自己想出了两种解决连接组件问题的方法:为了在它们之间做出决定,如果您能够(迅速)估计它们的复杂性并选择更好的方法,那将非常有用。
"So long as you are not dealing with huge data sets you will be fine not knowing complexity"
这通常是正确的,但并非总是如此。例如,O(n!)
即使对于相对较小的数据集,算法也将不可行。如果O(n!)
在可能使用的位置使用算法,则O(n^2)
在数据大小为10的情况下执行程序将花费36,288倍的时间。在数据量为20的情况下,您正在查看2.4亿亿次运算。
这是汤姆·范德赞丹(Tom van der Zanden)的回答的反驳,该回答指出这是必须的。
问题是,大多数情况下,慢50.000倍是没有关系的(当然,除非您在Google工作)。
如果您执行的操作耗时一微秒,或者您的N从未超过某个阈值(如今已完成很大一部分编码),则将不再重要。在这些情况下,考虑计算复杂性只会使您浪费时间(和最有可能的金钱)。
计算复杂性是一种工具,用于了解为什么某些事物可能变慢或扩展不良,以及如何进行改进,但大多数情况下完全是过度的。
我从事专业程序员已经有五年多了,但我从未发现在循环O(M * N)中循环时需要考虑计算复杂性,因为操作总是非常快,或者M和N如此快小。
对于从事编程工作的任何人来说,还有很多更重要,更常用和更难理解的东西(线程和性能分析是性能方面的好例子)。
当然,有些事情如果不了解计算复杂性是永远无法做的(例如:在字典上查找字谜),但是大多数时候您不需要它。
我从事软件开发工作已经有30年左右的时间了,无论是作为承包商还是员工,我都取得了很大的成功。我的第一语言是BASIC,但是我很快自学了机器语言,以摆脱动力不足的困扰。多年来,我在分析器中花费了很多时间,并且学到了很多有关生成快速,内存有效的优化代码的知识。
不管怎么说,我是自学成才的。直到几年前开始面试,我才遇到过O符号。除了面试期间,这在我的专业工作中从未出现过。因此,我不得不学习基础知识才能在面试中解决这个问题。
我感觉就像是爵士音乐家,不会读乐谱。我仍然可以打得很好。我了解哈希表(哎呀,在我知道哈希表已经被发明之前就发明了哈希表)和其他重要的数据结构,我什至可能知道一些它们在学校没有教授的技巧。但是我认为事实是,如果您想在这个行业中取得成功,您要么需要独立学习,要么学习他们在面试中提出的问题的答案。
顺便说一句,我最近采访了一位前端Web开发人员角色。他们问我一个问题,答案需要既有计算复杂性又需要对数的知识。我设法记得二十年前有足够的数学来或多或少正确地回答它,但这有点令人讨厌。我从未在任何前端开发中使用对数。
祝你好运!
这个问题是很主观的,所以我认为答案取决于它。
如果您处理少量数据,则没关系。在这些情况下,通常可以使用任何语言(例如,您的语言提供的标准库)。
但是,当您处理大量数据时,或者由于某些其他原因而坚持认为程序运行速度很快,则必须了解计算的复杂性。如果不这样做,您如何知道应该如何解决问题,或者甚至有多快可以解决问题?但是,仅仅了解理论还不足以成为一名真正的优秀程序员。我相信,要生成极快的代码,您还必须了解机器的工作方式(缓存,内存布局,指令集)以及编译器的工作方式(编译器会尽力而为,但并不完美)。
简而言之,我认为理解复杂性显然会使您成为更好的程序员。
如果正在开发重要算法的人不了解算法复杂性,肯定是一个问题。算法的用户通常依赖于具有良好性能特征的良好实现质量。虽然复杂度不是影响算法性能的唯一因素,但它是一个重要的因素。不了解算法复杂性的人不太可能开发具有有用性能特征的算法。
假设可用的算法质量很好,对于算法用户来说这不是什么大问题。对于使用具有重要的,明确指定的标准库的语言的开发人员而言,这是正确的-他们只需要知道如何选择满足那里需求的算法即可。问题出在库中它们有多种可用的某种类型的算法(例如,排序),因为复杂性通常是两者之间进行选择的标准之一。然后,不了解复杂性的开发人员将无法理解为手头的任务选择有效算法的基础。
还有一些开发人员专注于(需要更好的描述)非算法问题。例如,他们可能专注于开发直观的用户界面。这样的开发人员通常不必担心算法的复杂性,尽管它们可能再次依赖于高质量开发的库或其他代码。
它取决于开发的程序,但不取决于您正在使用的数据量,而是取决于您所做的工作类型。
让我们打电话给不了解概念复杂性的程序员。
笨拙的程序员可以执行以下操作:
笨拙的程序员不应该这样做:
因此,当您只想使用技术时,noobish程序员很好。因此,在开发新解决方案,自定义技术等方面,最好雇用那些没有笨拙的程序员。
但是,如果公司不开发新技术,则仅使用已经制造的技术。雇用熟练和有才华的程序员会浪费人才。同样的道理,如果您不想使用新技术,并且可以使用已经完成的框架将客户的想法放入设计和程序中,那么这将浪费您的时间,要学习您永远不需要的东西,除了如果这是您的爱好,并且您喜欢逻辑挑战。
我有点犹豫在这里写一个答案,但是由于我发现自己对其他几个人不屑一顾[我的一些评论开始聊天],所以我是这样看的...
计算中许多事物都有知识的水平/程度(这个术语,我的意思是计算机科学与信息技术的结合)。计算复杂性无疑是一个广阔的领域(您知道OptP是什么吗?还是Abiteboul-Vianu定理是什么?),并且也承认了很多深度:大多数具有CS学位的人都无法提供用于研究的专家证明。有关计算复杂性的出版物。
老实说,我敢于将知道何时应用计算复杂性概念(以及何时可以安全地忽略它们)与在C语言中实现一些对性能敏感的代码以及对性能不敏感的某种常见实践(在Java世界之外)进行比较。 (顺便说一句,这在Julia的谈话中称为“标准妥协”。)知道何时不必考虑性能可以节省编程时间,这也是相当有价值的商品。
还有一点是,了解计算复杂性并不会自动使您擅长优化程序。您需要了解更多与架构相关的内容,例如缓存局部性,[有时]流水线化,以及当今的并行/多核编程。后者既有自己的复杂性理论,又有实际考虑。后者来自2013年SOSP论文 “每个锁定方案都有15分钟的成名。在所有目标体系结构或工作负载上,我们认为这9个锁定方案都没有一个始终优于其他任何一个。严格来说,要寻求最优性,因此,应该根据硬件平台和预期的工作量来选择锁定算法。”
如果您不知道big-O,则应该学习它。这并不难,而且确实很有用。从搜索和排序开始。
我确实注意到,很多答案和评论都建议使用概要分析,并且它们几乎总是意味着使用概要分析工具。
问题是,就其在查找所需加速内容方面的有效性而言,分析工具无处不在。 在这里,我列出并解释了探查器遭受的误解。
结果是,如果程序比学术活动大,它们可能包含沉睡的巨人,即使是最好的自动探查器也无法暴露这些巨人。 这篇文章展示了一些如何从探查器中隐藏性能问题的示例。