Algorithm 有时用O(n^2)写解比用O(n)写解好吗?

Algorithm 有时用O(n^2)写解比用O(n)写解好吗?,algorithm,oop,Algorithm,Oop,如果我们有这样的问题解决方案: public void solutionLinear(Problem problem) { for (int i = 0; i < problem.getSize(); i++) { // do something with problem and compute solution } } 公共无效解决方案线性(问题){ 对于(int i=0;i

如果我们有这样的问题解决方案:

public void solutionLinear(Problem problem) {
  for (int i = 0; i < problem.getSize(); i++) {
     // do something with problem and compute solution
  }
}
公共无效解决方案线性(问题){
对于(int i=0;i
…如果我们有这样的问题解决方案

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
    }
  }
}
public void solutionquadrac(问题){
对于(int i=0;i

有时候和什么时候写第二个解决方案更好吗

大O复杂性度量忽略了常量系数,因此“O(N)复杂性”和“O(N^2)复杂性”分别大致对应于“在
A*N+B
s中运行”和“在
C*N^2+D*N+E
s中运行”。如果A&B较大而C&D&E较小,则后者可能更可取

考虑代码示例:

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();
    }
  }
}
公共无效解决方案线性(问题){
对于(int i=0;i

尽管是O(N^2),但只要
问题。getSize()
小于60,后一种算法就会运行得更快。

其他答案很好地解释了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)中运行的函数。但是使用更少的内存,你可能需要考虑较慢的算法。

这方面的一个很好的例子是快速排序与合并排序-一般来说,合并排序始终比快速排序快,但与合并排序不同,快速排序是就地完成的,不需要分配内存


总之

有时用O(n^2)写解比用O(n)写解好吗


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

在所有条件相同的情况下,O(n)总是比O(n^2)更可取。您为什么要编写低效的代码?代码“漂亮”“很少有人考虑把它弄得漂亮会让它像怀孕的母牛一样运转。这是工程师们通常说的话,但我不确定建筑师们。。。仅仅把代码的效率作为它的主要属性似乎是不成熟的,我想还有其他一些东西,但我没有足够的经验来证明这是真的。我没有说其他一切都是平等的,解决方案不可能是平等的。“难道我们不应该编写最简单、最愚蠢的解决方案,这就足够好吗?”不,你应该尽可能写出最好的代码。“为了可读性尽可能简单地编写”是一种倾向于冒泡排序而不是快速排序的心态,尽管快速排序有明显的优势。在DonaldKnuth的论文“StructuredProgrammingWithGoStatements”中,他写道:“程序员浪费大量时间考虑或担心其程序中非关键部分的速度,而在考虑调试和维护时,这些提高效率的尝试实际上会产生强烈的负面影响。我们应该忘记小效率,比如说97%的时间:过早优化是万恶之源。然而,我们不应该在这关键的3%上放弃我们的机会。“那么。。。。正是我说的:)或多或少。我认为我们从不同的角度得出了相同的结论:-)你是对的,先生:pI的目标是设计原则。您是否会实现与完全不可读的快速代码相反的可读性较慢的代码?我可能倾向于使用快速代码