在O(n ^ 2)中写入解决方案有时比在O(n)中写出更好吗?

时间:2016-02-03 19:43:18

标签: algorithm oop

如果我们能解决这样的问题:

public void solutionLinear(Problem problem) {
  for (int i = 0; i < problem.getSize(); i++) {
     // do something with problem and compute solution
  }
}

...如果我们有解决这样的问题

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
    }
  }
}

有时候写第二个解决方案更好吗?

3 个答案:

答案 0 :(得分:4)

大O复杂度测量省略了常数系数,因此“O(N)复杂度”和“O(N ^ 2)复杂度”大致对应于“在A*N + B秒内运行”和“在{{1}中运行”分别是“秒”。如果A&amp; A,则后者可能是优选的。 B很大,C&amp; D&amp; E很小。

考虑代码示例:

C*N^2 + D*N + E

尽管是O(N ^ 2),但只要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(); } } } 小于60,后一算法就会运行得更快。

答案 1 :(得分:2)

其他答案很好地解释了O(n ^ 2)解决方案实际上比O(n)解决方案更快的情况,因此我将重点关注问题的另一方面,即& #34;你是否赞成可读性而非性能?&#34;

简答:否

长答案:一般没有。有时,性能差异足够小,以至于您从可读性中获得的收益可能是值得的。例如,人们争论开关和if / else语句的相对速度,但性能上的差异是如此之小,以至于您应该只使用对您和您的团队来说更易于维护的那个。

除了这些情况之外,放慢程序速度的可能性通常会超过从可读代码中获得的收益。如果它是编写良好的代码并且唯一的问题是算法更复杂,那么您可以通过留下文档供下一个人使用来解决该问题。

我认为这种权衡的一个好例子是冒泡排序与快速排序。冒泡排序是一种非常容易理解的算法,并且非常易读。另一方面,快速排序远不那么直观,而且难以阅读。但是,在生产代码中用冒泡排序替换快速排序是不合适的,因为性能差异太极端。你问的情况甚至比这更糟,因为你在谈论O(n)vs O(n ^ 2)而bubble-sort vs quick-sort是O(n)vs O(log(n))(在最好的情况当然)。

答案 2 :(得分:1)

何时加速

特别是涉及到运行时,其他人通常说的是正确的;每当你引用Big O中的函数时,通常都会有一个隐藏常量。如果具有O(n ^ 2)的函数具有相对较小的常量且运行时间不长,则可能是比使用大常数运行O(n)并且运行时间更长的函数更快。

不要忘记记忆

运行时不是在编写或使用算法时要考虑的事情;你还需要担心空间的复杂性。如果你碰巧需要在你的应用程序中节省内存,你必须选择在O(n)中运行但使用大量内存的函数和在O(n ^ 2)中运行但使用更少内存的函数,你可能想要考虑那种较慢的算法。

这方面的一个很好的例子是快速排序与合并排序 - 通常,mergesort始终比快速排序更快,但是快速排序已经到位并且不需要分配内存,这与mergesort不同。

结论

  

在O(n ^ 2)中写入解决方案有时比在O(n)中编写解决方案更好吗?

,考虑到您的应用程序的具体情况,较慢的选项可能确实是更好的选项。你永远不应该因为速度慢而排除算法!