Confused on Big Oh

Started by
35 comments, last by jwezorek 11 years, 1 month ago

This is completely made-up and a very forced example, but imagine two different algorithms with loops like below, where they both call some inner function (DoAlgorithmInner1/DoAlgorithmInner2) that we assume are both of equal cost.


for( i=0; i < n; ++i )
  for( j=0; j < 100; ++j )
    DoAlgorithmInner1( i, j )


for( i=0; i < n; ++i )
  for( j=0; j < n; ++j )
    DoAlgorithmInner2( i, j );
The first is O(n*100), which is O(n*constant), which is just O(n).
The second is O(n2).

Say that n is only 10 -- the first one calls the inner function 10*100 times, the second calls it 10*10 times.
Say that n is 10000 -- the first one calls the inner function 10000*100 times, the second calls it 10000*10000 times.

So for any case where n is less than 100, the n^2 algorithm actually does less work.


For a real world example -- try implementing a comparison sort, like quicksort, which is O(n log n) and also a radix sort, which is O(n).
The constants, which are removed from the big-O analysis are actually very high with the radix sort, which makes it behave like the above example.
e.g. n*1000 might be more expensive than n*n*10.

Nice example and clear explaination

Advertisement

Big-O notation is useful in CS theory classes, but in the practical world it only serves as a general guide to see if an algorithm is sane or not for the problem you are trying to solve.

Good to know. sleep.png

It's still important to use in those situations, though. EvE Online has some really horrific lag because the legacy code uses some algorithms with really horrific scalability. For a game that encourages fights between hundreds of players on the same battlefield at the same time this was a really bad design flaw and it ended up being one of the factors that eventually cost them a lot of users and apparently a lot of frustration for the poor saps who have to climb through the spaghetti to try and optimize things. I remember reading the dev blogs back when I was playing EvE about how they finally got their automated test client running and lo-and-behold there was O(n^2) crap popping up all over the place just for the normal, inescapable frame logic. The first one they found: the game was actually composing a list of every item on grid - FOR every item on grid. That is, for every pilot on the grid the server would create a list of everything on the grid and send it to that pilot, then discard it and create more or less the same damn list for the next player, etc, etc. Needless to say once you get a thousand ships on a grid things start to break.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
&nbsp;

I'm been reading the definition on Big-Oh but I want to test if I interpret it right using my own words. The book I'm using does not provide examples and also uses a rather complicated and dry definition. So I will make examples to test if my knowledge on Big Oh holds true.
&nbsp;
In my own words, Big Oh is used when you have the growth of a function on the left less than or equal to the growth of a function on the right.
&nbsp;
My examples should be correct based on what I stated
&nbsp;
n^2 = O n^2
&nbsp;
n^2 = O n^3

&nbsp;
Big Oh notation gives a worst case estimate on how often data needs to be inspected to run the algorithm it is defined for. Little o gives the lower bound and capital theta gives the lower and upper bounds in one function.

In CS however we are usually only interested in the worst case scenario as it is better to optimise the algorithm for that case.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

if something ( A ) is in the big Oh of something else ( B ), ignoring everything but the n's in each sides

B will eventually be larger than A ( from any n towards infinity ).

The main purpose of this is to check the efficiency of a piece of code

https://en.wikipedia.org/wiki/Time_complexity#Table_of_common_time_complexities

^ this is probably all you need to know

also Big Oh is for the worst case

basic example:

if you loop through all n elements in an array to find a specific element, worst case scenario you will go through all n elements, so we say the code will run in the big oh of n.

Big Oh notation gives a worst case estimate on how often data needs to be inspected to run the algorithm it is defined for. Little o gives the lower bound and capital theta gives the lower and upper bounds in one function.

In CS however we are usually only interested in the worst case scenario as it is better to optimise the algorithm for that case.

No, O, o and Theta talk about the asymptotic rates of growth of functions. In CS we often use them to express facts about the growth in resource consumption (most often CPU time or memory) for an algorithm as a function of the length of the input.

It is extremely common to be interested in the average case, especially if you are going to be running the algorithm many times.

if something ( A ) is in the big Oh of something else ( B ), ignoring everything but the n's in each sides

B will eventually be larger than A ( from any n towards infinity ).

Not true. 10*n = O(n), and yet n will never be larger than 10*n.

also Big Oh is for the worst case

No, it's not only for that. That notation is also used for the average performance, and for the amortized performance.

basic example:

if you loop through all n elements in an array to find a specific element, worst case scenario you will go through all n elements, so we say the code will run in the big oh of n.

It's also the case that in the average you expect to go through n/2 elements, assuming the element is in the array. So you also say that the code will take time O(n) in the average, because O(n/2) and O(n) are the same.


Big Oh notation gives a worst case estimate on how often data needs to be inspected to run the algorithm it is defined for. Little o gives the lower bound and capital theta gives the lower and upper bounds in one function.

In CS however we are usually only interested in the worst case scenario as it is better to optimise the algorithm for that case.

No, O, o and Theta talk about the asymptotic rates of growth of functions. In CS we often use them to express facts about the growth in resource consumption (most often CPU time or memory) for an algorithm as a function of the length of the input.

It is extremely common to be interested in the average case, especially if you are going to be running the algorithm many times.

if something ( A ) is in the big Oh of something else ( B ), ignoring everything but the n's in each sides

B will eventually be larger than A ( from any n towards infinity ).

Not true. 10*n = O(n), and yet n will never be larger than 10*n.

also Big Oh is for the worst case

No, it's not only for that. That notation is also used for the average performance, and for the amortized performance.

basic example:

if you loop through all n elements in an array to find a specific element, worst case scenario you will go through all n elements, so we say the code will run in the big oh of n.

It's also the case that in the average you expect to go through n/2 elements, assuming the element is in the array. So you also say that the code will take time O(n) in the average, because O(n/2) and O(n) are the same.


Big oh is worse case only, it expresses the upper bound growth function on the algorithm not the average case. Even in an unsorted array a binary search will at worst case need n log(n) accesses to find an element that is at least equal to the one you specified, given that the value you are searching for should be in that array. Even in that case you could find an element that is the one your are looking for in the first go and that could happen 90% of the time. Big oh says nothing about the average case it only mentions something about the worst case behaviour of your algorithm.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

Big oh is worse case only, it expresses the upper bound growth function on the algorithm not the average case. Even in an unsorted array a binary search will at worst case need n log(n) accesses to find an element that is at least equal to the one you specified, given that the value you are searching for should be in that array. Even in that case you could find an element that is the one your are looking for in the first go and that could happen 90% of the time. Big oh says nothing about the average case it only mentions something about the worst case behaviour of your algorithm.

Do you have a reference for any of that? Who told you that you can only use big-O notation for worst-case performance?

But, since I am the one claiming that it is used for other things, the burden of proof is on me. Well, all I need to do is give you an example. Let me quote you the first two sentences from the Wikipedia article on Quicksort:

quicksort, or partition-exchange sort, is a sorting algorithm that, on average, makes O(n log n) comparisons to sort n items. In the worst case, it makes O(n2) comparisons, though this behavior is rare.

Right there, you see a use of big-O notation for the average case.

EDIT: And a bunch of examples in one place (a whole table, actually): http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms

Quote

name='Wikipedia']
quicksort, or partition-exchange sort, is a sorting algorithm that, on average, makes O(n log n) comparisons to sort n items. In the worst case, it makes O(n2) comparisons, though this behavior is rare.

Right there, you see a use of big-O notation for the average case.

EDIT: And a bunch of examples in one place (a whole table, actually): http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms

Tragically you gave an example of incorrect usages of Big-O notation.

Big-O notation is only for worst case growth of a function. Please refer to the formal definition also provided on wikipedia or any number of math texts. (Formal definition on wikipedia as I can't link to math texts: http://en.wikipedia.org/wiki/Big_O_notation#Formal_definition)

Now - that doesn't mean that the Big-O for a particular function can't be the same as one or even all of the 5 Bachmann-Landu notations. Consider the very simple case of an algorithm that goes through a list of n numbers and adds 1 to each number. That would take n operations exactly - which means its worst case is n, its average case is n, and its best case is also n.

If you read the paragraph just above the table you mentioned the author states:

The run time and the memory of algorithms could be measured using various notations like theta, omega, Big-O, small-o, etc. The memory and the run times below are applicable for all the 5 notations.

Please see the following for an explanation of the other notations used: http://en.wikipedia.org/wiki/Big_O_notation#Related_asymptotic_notations

Outside of theoretical CS - you probably won't be seeing the other notations, as the common practice seems to be simply to abuse Big-O and use it everywhere even if it is an incorrect usage.

Quote

name='Wikipedia']
quicksort, or partition-exchange sort, is a sorting algorithm that, on average, makes O(n log n) comparisons to sort n items. In the worst case, it makes O(n2) comparisons, though this behavior is rare.

Right there, you see a use of big-O notation for the average case.

EDIT: And a bunch of examples in one place (a whole table, actually): http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms

Tragically you gave an example of incorrect usages of Big-O notation.

Big-O notation is only for worst case growth of a function. Please refer to the formal definition also provided on wikipedia or any number of math texts. (Formal definition on wikipedia as I can't link to math texts: http://en.wikipedia.org/wiki/Big_O_notation#Formal_definition)

Now - that doesn't mean that the Big-O for a particular function can't be the same as one or even all of the 5 Bachmann-Landu notations. Consider the very simple case of an algorithm that goes through a list of n numbers and adds 1 to each number. That would take n operations exactly - which means its worst case is n, its average case is n, and its best case is also n.

If you read the paragraph just above the table you mentioned the author states:

>The run time and the memory of algorithms could be measured using various notations like theta, omega, Big-O, small-o, etc. The memory and the run times below are applicable for all the 5 notations.

Please see the following for an explanation of the other notations used: http://en.wikipedia.org/wiki/Big_O_notation#Related_asymptotic_notations

Outside of theoretical CS - you probably won't be seeing the other notations, as the common practice seems to be simply to abuse Big-O and use it everywhere even if it is an incorrect usage.

If anyone is interested in hearing what's wrong with that post, please ask and I will explain. Otherwise, I won't waste my time.

[...]

Tragically you gave an example of incorrect usages of Big-O notation.

[...]

Outside of theoretical CS - you probably won't be seeing the other notations, as the common practice seems to be simply to abuse Big-O and use it everywhere even if it is an incorrect usage.

It isn't true that Big-O = worst case, Big-Omega = best case, and Big-Theta = average case.

Big-O = upper bound. We are often interested in an upper bound on the worst case so Big-O gets associated with worst case behavior, but we can also be interested in an upper bound on average case behavior, etc.

This topic is closed to new replies.

Advertisement