-4

If we have solution to problem something like this:

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

...and if we have solution to problem which is like this

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

Is it better to write second solution sometimes and when?

Dejan Pekter
  • 705
  • 3
  • 18
  • all things being equal, O(n) is always going to be preferable over O(n^2). why would you want to write inefficient code? code "prettiness" rarely enters consideration making it pretty makes it run like a pregnant cow. – Marc B Feb 03 '16 at 19:44
  • That is what engineers usually say, I'm not sure about architects though... It seems immature to think only about efficiency of code as its main property, there are other things I guess but I'm not experienced enough to claim it is true. – Dejan Pekter Feb 03 '16 at 19:46
  • I didn't state that everything else is equal, solutions can't be equal. – Dejan Pekter Feb 03 '16 at 19:49
  • well, then consider a practical example: a trucking firm's route scheduler. if their scheduler creates a route with n^2 stops for n deliveries, they're going to be out of business because of delayed deliveries/fuel overhead because their competitor only needs `n` stops to accomplish the same thing. – Marc B Feb 03 '16 at 19:49
  • Its very likely a misunderstanding of the problem. I cannot think of any scenario where both linear and quadratic approaches existed to solve and the quadratic one was better. – Ravindra HV Feb 03 '16 at 19:51
  • Ok, so example is you have really small case, like 10 elements in array, whether you would do it O(n^2) or O(n) it really doesn't make any difference. Algorithm though for O(n^2) is something you (as good engineer) wouldn't ever write because it is just too obvious that it can be done a little bit harder (for you) in O(n). From the other hand college hire would understand O(n^2) algorithm right away, and it would take him 2 hours to understand O(n) algorithm. If you need to add new condition O(n^2) is probably better also. :) – Dejan Pekter Feb 03 '16 at 19:52
  • Ok, you got me guys, this was a trick question... I just wanted to understand why we (engineers) have passion for writing complex solutions and not simple ones. If engineer is really smart, he will do bug free complex solution and be happy with it, but we shouldn't we should write simplest and most stupid solution that is just good enough and be happy about it's simplicity and extensibility, until we need optimisation, in my opinion. – Dejan Pekter Feb 03 '16 at 19:55
  • @SalvadorDali it partly answers, but I want to focus on premature optimisation on this question. – Dejan Pekter Feb 03 '16 at 19:56
  • 1
    "Shouldn't we write simplest and most stupid solution that is just good enough?" No, you should write the best code you can. The "write it as simply as possible for the sake of readability" is the kind of mindset that prefers bubble-sort to quick-sort despite the obvious superiority of quick-sort. – Kevin Feb 03 '16 at 21:28
  • I'm not speaking of general purpose libraries, I'm speaking of solving one particular problem. "The best code" is far from "The most efficient code" in my opinion. Optimisation is usually contradicting design. It also happens that when you optimise stuff you make your code less extensible. I think it is like making a car as fast as possible without thinking about how people would use it. :) – Dejan Pekter Feb 03 '16 at 21:37
  • 2
    In DonaldKnuth's paper "StructuredProgrammingWithGoToStatements", he wrote: "Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%." – Dejan Pekter Feb 03 '16 at 22:23

3 Answers3

4

Big O complexity measurements omit constant coefficients, so "O(N) complexity" and "O(N^2) complexity" roughly correspond to "runs in A*N + B seconds" and "runs in C*N^2 + D*N + E seconds" respectively. The latter may be preferable if A & B are large and C & D & E are small.

Consider the code samples:

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();
    }
  }
}

Despite being O(N^2), the latter algorithm will run faster as long as problem.getSize() is less than 60.

Kevin
  • 74,910
  • 12
  • 133
  • 166
  • So.... exactly what I said :) – Idos Feb 03 '16 at 19:52
  • More or less. I think we're approaching the same conclusion from different angles :-) – Kevin Feb 03 '16 at 19:53
  • You are correct sir :p – Idos Feb 03 '16 at 19:53
  • I was aiming on design principles answer. Would you implement slower code that is readable in opposite to fast code that is completely unreadable? – Dejan Pekter Feb 03 '16 at 21:20
  • I'd probably lean towards fast+unreadable, and supplement it with detailed explanatory comments and possibly an apology. – Kevin Feb 03 '16 at 21:23
  • In my experience it is rare to come across a problem that can't be written in a fast and readable way that can be written in a slow and readable way, and in those rare cases, you should just leave a comment or documentation of what it is doing and why you left it in an unreadable state – Kevin Feb 03 '16 at 21:24
2

The other answers do a good job of explaining the situation where a O(n^2) solution is actually faster than a O(n) solution, so I will be focusing on the other side of the question, namely, "Should you favor readability over performance?"

Short Answer: No

Long Answer: Generally no. There are times when the difference in performance is small enough that the gains you get from readability might be worth it. For example, people debate over the relative speed of switches and if/else statements, but the difference in performance is so small that you should really just use whichever is more maintainable for you and your team.

Outside of those cases, the potential for slowing down your program generally outweighs the gain you get from the code being readable. If it is well written code and the only problem is that the algorithm is more complex, you can solve that problem by leaving documentation for the next person to work on it.

I think a good example of this trade-off is bubble-sort vs quick-sort. Bubble-sort is a very easy algorithm to understand and is very readable. Quick-sort on the other hand is far less intuitive and definitely harder to read. However, it would not be appropriate to replace quick-sort with bubble-sort in production code because the performance difference is too extreme. The situation you asked about is even worse than that because you are talking about O(n) vs O(n^2) whereas bubble-sort vs quick-sort is O(n) vs O(log(n)) (in the best case of course).

Kevin
  • 551
  • 1
  • 9
  • 28
  • 4
    I would add that there are situations where the asymptotic behavior is insignificant in the scope of a given problem. E.g., if you know that your input is always limited to 10 values, it doesn't really matter what to use - quicksort or bubble sort. – SomeWittyUsername Feb 03 '16 at 21:58
  • 1
    Yep, I just figured the other answers covered that topic sufficiently – Kevin Feb 03 '16 at 22:03
  • Exactly, and also there are sizes of arrays where n^2 sort may be faster than nlogn sort. Usually libraries do for example combination of merge sort and insertion sort to ensure when array is small enough, they use faster algorithm for small arrays. – Dejan Pekter Feb 03 '16 at 22:03
  • @Deximat That can be true but be careful when operating with big-O notations. Whether or not O(n^2) can be faster than O(nlogn) depends not only on n but also on the specific constants of the algorithm, as mentioned in other answers. – SomeWittyUsername Feb 03 '16 at 22:09
  • I know, I was algorithm competitor :) I intentionally flamed this topic because I wanted to see if most engineers only see "engineering" part of problem solving or there are people thinking about value, effort and impact of complex solutions to readability, test effort, maintainability ability to change in future. There are many aspects which are hidden from programers these days. – Dejan Pekter Feb 03 '16 at 22:14
  • 3
    So you asked this as a test for the people on SO? That's a weird reason to ask a question here, and not a particularly useful way to use the site – Kevin Feb 03 '16 at 22:36
1

When It Comes to Speed

When it comes to runtime in particular, what generally everyone else is saying is right; there usually is a hidden constant whenever you refer to a function in Big O. If the function with the O(n^2) had a relatively small constant and didn't run particularly long, it could be faster than a function which ran O(n) with a large constant and ran longer.


Don't Forget About Memory

Runtime isn't the only thing to consider when writing or using an algorithm; you also need to worry about the space complexity. If you happened to need to conserve memory in your application and you had to choose between a function which ran in O(n) but uses a ton of memory and a function which ran in O(n^2) but uses much less memory, you might want to consider that slower algorithm.

A good example for this is quicksort vs. mergesort - in general, mergesort is consistently faster than quicksort, however quicksort is done in place and doesn't require allocating memory, unlike mergesort.


In Conclusion

Is it sometimes better to write solution in O(n^2) than in O(n)?

Yes, considering the specific circumstances of your application, the slower option may indeed be the better one. You should never rule out an algorithm simply because its slower!

Nick Zuber
  • 5,467
  • 3
  • 24
  • 48