views:

822

answers:

7

I am learning algorithm analysis. I am having trouble understanding the difference between O, Ω, and Θ.

The way they're defined is as follows:

  • f(n) = O(g(n)) means c · g(n) is an upper bound on f(n). Thus there exists some constant c such that f(n) is always ≤ c · g(n), for large enough n (i.e., n ≥ n0 for some constant n0).
  • f(n) = Ω(g(n)) means c · g(n) is a lower bound on f(n). Thus there exists some constant c such that f(n) is always ≥ c · g(n), for all n ≥ n0.
  • f(n) = Θ(g(n)) means c1 · g(n) is an upper bound on f(n) and c2 · g(n) is a lower bound on f(n), for all n ≥ n0. Thus there exist constants c1 and c2 such that f(n) ≤ c1 ·g(n) and f(n) ≥ c2 ·g(n). This means that g(n) provides a nice, tight bound on f(n).

The way I have understood this is:

  • O(f(n)) gives worst case complexity of given function/algorithm.
  • Ω(f(n)) gives best case complexity of given function/algorithm.
  • Θ(f(n)) gives average case complexity of given function/algorithm.

Please correct me if I am wrong. If it is the case, time complexity of each algorithm must be expressed in all three notations. But I observed that it's expressed as either O, Ω, or Θ; why not all three?

+25  A: 

Θ denotes an asymptotically tight upper and lower bound.

O denotes an upper bound, but this bound might or might not be tight.
o denotes an upper bound that is not tight.

Ω denotes a lower bound, but this bound might or might not be tight.
ω denotes a lower bound that is not tight.

Can Berk Güder
Introduction to Algorithms, 2nd Ed., p.47:The asymptotic upper bound provided by O-notation may or may not be asymptotically tight. The bound 2n^2 = O(n^2) is asymptotically tight, but the bound 2n = O(n^2) is not. We use o-notation to denote an upper bound that is not asymptotically tight.
Can Berk Güder
I have upvoted you. You answer is correct.
Prasoon Saurav
It's correct as written now. I take back my downvote in spirit, but SO won't let me undo.
danben
@danben: I made an invisible edit, so you ought now to be able to change your vote.
Jim Ferrans
That worked, thanks
danben
+1  A: 

Everything you've said is pretty much correct; we don't talk about all three every time we analyze an algorithm because that would generally be too time-consuming. But sometimes we do, if the cases differ greatly.

If an algorithm's worst case is the same as its average case, or even sometimes when the worst case is very rare, programmers will just talk about big-O because this has become standard procedure. More of a convention than anything.

If there's anything else that you're asking that I didn't get to, please clarify the question and I'll check back. Particularly, the last sentence is a little vague - you said you observed its expressed as just one of the three. Where?

danben
The only thing that I would add is that Big-O normally makes senses when you have no information about the input to the algorithm and so you cannot deppend on the algorithm running any faster. Otherwise you can use Ω or Θ to get a more pragmatic idea of how the algorithm will run.
aubreyrhodes
Actually, asymptotic notation has very little to do with best/worst/average case analysis. For example, Quicksort has Θ(n lg n) average case performance, but has Θ(n^2) worst case performance.
Can Berk Güder
reading your answer again, I realized you were actually trying to say the same thing. sorry.
Can Berk Güder
Yes, I agree it could be clearer though.
danben
+5  A: 

These are some of the resources that will really help you:

codaddict
+21  A: 

It is important to remember that the notation, whether O, Ω or Θ, expresses the asymptotic growth of a function; it does not have anything intrinsically to do with algorithms per se. The function in question may be the "complexity" (running time) of an algorithm, either worst-case, best-case or average-case, but the notation is independent of where the function comes from.

For example, the function f(n)=3n2+5 is:

  • O(n2), it is also O(n2log n), O(n3), O(n4) and so on, but is not O(n).
  • Ω(n2), it is also Ω(n log n), Ω(n) and so on, but is not Ω(n3).
  • Θ(n2). It is not even Θ(n2log n) or Θ(n2/log n).

Now, usually the function considered is the worst-case complexity of an algorithm, and which notation of the three is used depends on what we want to say about it and on how carefully we do the analysis. For example, we may observe that because there are two nested loops, the worst-case running time is at most O(n2), without caring about whether this is actually achieved for some input. (Usually it is obvious that it is.) Or, we may say that the worst-case running time of sorting is Ω(n log n), because there must be some inputs for which it must take at least cn(log n) steps. Or, we may look at a particular mergesort algorithm, and see that it takes at most O(n log n) steps in the worst-case and that some input makes it take n log n steps, so the worst-case running time is Θ(n log n).

Note that in all the three examples above, it was still the same (worst-case) running time that was being analyzed. We may analyze the best-case or average-case instead, but again, which notation of the three we use depends on what we want to say — whether we want to give an upper bound, lower bound, or tight bound on the order of growth of the same function.

ShreevatsaR
+4  A: 

For what those three mean, see Can Berk Güder's answer.

Note also that they have nothing at all to do with best case, worst case, and average case. Bubble sort for example is Θ(n) best case (because if the data is already sorted, only n-1 comparisons are needed), and Θ(n^2) worst case. It's Θ(n^2) average-case assuming randomly-shuffled input. That average case therefore is also O(n^2), and O(n^3), and O(2^n).

So, O, Θ and Ω tell you what kind of bound it is. They don't tell you what the bound is a limit on. In context, it might be a limit on the best case, the worse case, the average case, or the algorithm as a whole (all cases).

Of course if an algorithm has Ω(g) best case, then it is itself Ω(g). If it has O(g) worst case it is O(g). So there is a relation there. But if it has Θ(g) average case, that tells you almost nothing about the best and worst cases.

As for "why not all three?".

If your function is Θ(g), then it is also O(g) and Ω(g). So there's not much point providing other bounds alongside a Θ bound.

When you see one of the others alone, it's generally because we only care about an upper bound, or we only care about a lower bound. So we say that all comparison sorts are necessarily Ω(n log n) worst case, and that bubble sort is O(n^2) worst case but O(n) best case, because we aren't trying to fully describe the time complexity, we're just expressing the bounds we care about in a particular context.

And in any case most people seem to be lazy, and don't want to have to type Greek letters. I know I am. So we just say that comparison sorts are "at best O(n log n)". It's an abuse of notation really, but it gets the point across.

Steve Jessop
The other definition is also fine, and is in use. We usually have nice functions as g (we only need positive, actually), so we can always account for the first few M (finitely many) by picking a larger constant c.
ShreevatsaR
True, but the full definition accounts for functions which are not defined everywhere, and for functions of real numbers rather than just integers. For example, 1/x is O(1) by the proper definition, as are 1/(x-1), 1/((x-1)*(x-2)), etc, without having to make special conditions to account for their limited domains. I guess if you're not a mathematician, the definitions amount to the same thing, by the principle of "it's obvious what I mean" ;-). But there is a difference between an asymptotic limit at infinity (my defn) and a plain limit (your defn), and the difference is the business with M.
Steve Jessop
Oh yes, and the other edge case I already mentioned is something like f(n) = n + 1, g(n) = n^2. Then f is O(g), even though there obviously isn't a c such that n + 1 <= c * n^2 for n = 0. But looking at the question, it does specify "large enough n" in the definitions. So I suspect I hallucinated that it didn't, and I'll remove that bit of my answer.
Steve Jessop
Good point: the "large enough N" definition *is* less restrictive... the two definitions just are the same whenever it's obvious they are. :-) (E.g. for discrete domain, starting at n≥1, g is positive-valued, etc.)
ShreevatsaR
A: 

Big-O notation is often referred to as complexity of an algorithm because it assures us, that the algorithm will not perform substantially more worse for large n. However, as was rightly pointed out earlier, the Big-O gives us the asymptotic evaluation and our algorithm may behave differently when certain input is given. For example quick sort can be O(n^2), when the array is already sorted. OTOH, asymptotic situation may be improved in practice with neat implementation.

D_K
A: 

Was answered (at least partly) here:

martinus