Is it sometimes better to write solution in O(n^2) than in O(n)?
如果我们有类似这样的问题的解决方案:
1 2 3 4 5 | public void solutionLinear(Problem problem) { for (int i = 0; i < problem.getSize(); i++) { // do something with problem and compute solution } } |
…如果我们能解决这样的问题
1 2 3 4 5 6 7 | public void solutionQuadric(Problem problem) { for (int i = 0; i < problem.getSize(); i++) { for (int j = 0; j < problem.getSize(); j++) { // do something with problem and compute solution } } } |
有时候和什么时候写第二个解决方案更好吗?
大O复杂度测量忽略了常数系数,因此"O(N)复杂度"和"O(N^2)复杂度"分别大致对应于"在
考虑代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public void solutionLinear(Problem problem) { for (int i = 0; i < problem.getSize(); i++) { do_stuff_taking_one_hour(); } } public void solutionQuadric(Problem problem) { for (int i = 0; i < problem.getSize(); i++) { for (int j = 0; j < problem.getSize(); j++) { do_stuff_taking_one_second(); } } } |
尽管是O(n^2),但只要
其他答案很好地解释了O(n^2)解决方案实际上比O(n)解决方案更快的情况,因此我将重点讨论问题的另一方面,即,"您是否应该赞成可读性而不是性能?"
简短回答:否
长话短说:通常不会。有时性能上的差异很小,以至于从可读性中获得的收益可能是值得的。例如,人们对交换机的相对速度和if/else语句进行了争论,但是性能上的差异非常小,所以您应该真正使用对您和您的团队来说更易于维护的语句。
除这些情况外,降低程序速度的潜力通常大于从代码可读性中获得的收益。如果代码编写得很好,唯一的问题是算法更复杂,那么您可以将文档留给下一个人来处理,从而解决这个问题。
我认为这种权衡的一个好例子是泡沫排序与快速排序。气泡排序是一种非常容易理解和可读的算法。另一方面,快速排序的直观性要差得多,而且绝对难以阅读。然而,在生产代码中用冒泡排序代替快速排序是不合适的,因为性能差异太大。你问的情况甚至比这更糟,因为你说的是O(n)vs O(n^2),而气泡排序vs快速排序则是O(n)vs O(log(n))(当然是最好的情况)。
在速度方面
特别是当涉及到运行时时,通常其他人都说的是对的;每当在大o中引用函数时,通常都会有一个隐藏常量。如果带有o(n^2)的函数有一个相对较小的常量,并且运行的时间不长,那么它可能比使用大常量运行o(n)并运行很长时间的函数更快。呃。
别忘了回忆
在编写或使用算法时,运行时并不是唯一需要考虑的问题;还需要担心空间复杂度。如果你碰巧需要保存应用程序中的内存,你必须在运行在O(n)中的函数之间进行选择,但是使用一吨内存和一个运行在O(n ^ 2)中的函数,但是使用更少的内存,你可能需要考虑较慢的算法。
一个很好的例子是QuaskRoad与MyGeSoRoT——一般来说,MyGeSoRT始终比Quasr排序更快,但是QueQuoT是在适当的位置完成的,并且不需要分配内存,这与GysErrt不同。
总之
Is it sometimes better to write solution in O(n^2) than in O(n)?
是的,考虑到应用程序的具体情况,速度较慢的选项可能确实更好。你不应该仅仅因为一个算法慢而排除它!