On Thu, Nov 29, 2001 at 11:34:24AM -0800, Chris Thorpe wrote:
> 
> On Thu, 29 Nov 2001, Yanick wrote:
> 
> > On Thu, Nov 29, 2001 at 01:34:02PM -0500, Michael G Schwern wrote:
> >
> >>> Yesterday, I saw an interesting related exercise.  Write a program that
> >>> reads the lines from a file and outputs the middle line.  The kicker is
> >>> that you can't use arrays.
> > >
> > > I'll interpret that as O(1) memory, O(n) time.
> 
>   You can't do it in O(1) memory and O(n) time.
<snip>
>   If you elect to use O(1) memory, then you have to use O(1.5*n) time,
> as the already submitted examples do.
> 
>   It seems silly to try to use O(n/2) memory if you aren't allowed to use
> an array.

O(n) == O(1.5*n) == O(n/2).


A Crash Course On BigO Notation As Presented By A Guy Who Failed
Fundamental Data Structures And Algorithms 1 *

    O(1) means it runs in a fixed amount of time regardless of how much
         data is to be processed.  A hash is an O(1) algorithm.

    O(logn) means as you increase the amount of data, the time required
            will increase logarithmicly.  In order to double the run time
            you have to exponentially increase the data.

    O(n) means that as you increase the amount of data, the amount
         of time required will increase as well.  Double the data,
         double the run time.  Iterating through the lines of a file
         or elements of an array is O(n).

    O(n**2) [order n squared] means that as you increase the amount of
            data, the amount of time required will increase exponentially.
            Double the data, quadruple the run time.

    etc...

Here's the tricky part... constants are ignored.  An algorithm that
reads each line in a file once is O(n).  An algorithm that reads each
line in a file twice is O(n).  Even if it reads each line 10,000 times
it's still O(n).  This is because if you double the size of the file,
you only double the run-time.

So O(1.5*n) == O(n).

BigO is an expression of how the algorithm will perform as the data
size approaches infinity.  It is also refered to as worst-case
analysis.  As such it's a tad conservative.  There's also best-case
analysis and average-case analysis, I forget the symbols... theta or
something.  A basic quicksort is O(n**2), but this only happens if you
try to quicksort an already sorted array.  It's average case is nlogn.
Most practical quicksort implementations have safeguards to prevent
their worst case.

So when someone says "You're allowed O(1) memory and O(n) time to read
this file" it means that no matter how big the file, your algorithm
can only use a fixed amount of memory.  And if the size of the file
doubles, your program will run in twice the time.


Constants become useful again when comparing the run-time of
algorithms with the same BigO notations.  They also become useful when
the amount of data involved is relatively small or the constant involved
in "better" algorithm is prohibatively high.  This is why this:

    my @sorted_keys = sort keys %hash;

is usually more efficient than trying to replace the %hash with some
structure that keeps the keys always sorted, like a tree.


* If you check under your seats you'll find a packet of salt tablets.
Try not to mix them up with the suicide pill.


-- 

Michael G. Schwern   <[EMAIL PROTECTED]>    http://www.pobox.com/~schwern/
Perl Quality Assurance      <[EMAIL PROTECTED]>         Kwalitee Is Job One
IMHO bugs in Perl 5 shouldn't carry over to Perl 6. (Unless, of course,
we *like* the bugs... ;)
        -- Ken Fox in <[EMAIL PROTECTED]>

Reply via email to