Docs

advertisement

Determining complexity for recursive algorithms

In order to determine complexity before we actually code the algorithm, we need to analyze the pseudo code.

Estimating complexity for recursive code is difficult for many.

In the ILM to the left, you are asked to describe the recursive code in terms of code parameters.

New Problem randomly generates new problems for you to examine.

Or you can specify arameters, and the code is automatically updated to reflect your selections.

Click Animation to illustrate the amount of work done by all the recursive calls. Note the following conventions:

1. Each function call is represent by a horizontal bar. The area of the bar represents the number of operations executed by that function call.

2. As the current function calls additional instances, the work for the recursive calls is shown on the bar below.

Try the following example:

Work for a single call: n

Recursive Calls : 1

Recursive Parameter: n/2

Initial n value: 16

Notice bars appear at five levels (indicating that five calls to doit are made).

You will need to mentally rearrange the blocks to determine its complexity.

Note that the four lower blocks can be placed end to end to create a block which is n-1 in length. Thus, the total run time is proportional to 2n, which is a complexity of O(n)

Try the following example:

Work for a single call = n

Recursive Calls : 2

Recursive Parameter: n/2

Initial n value: 16

Press Animation to see the amount of work performed.

In this case, the work fills in a rectangle. The two bars in row two indicate that the initial call to doit calls doit two more times, but each does only half the work of the original call to doit. The order in which the bars are shown indicates the order in which the corresponding calls are executed.

After all calls are completed, the width is n and the height is log n +1. Thus the complexity is O(n log n).

Determining the height is confusing for some. You are asking, "How many times can I divide n in half and have anything left?" The answer is log n.

This visual way of computing recursive complexity is much better than merely memorizing formulas or computing the complexity with "telescoping" or other techniques. It is easy to do and easy to remember.

Try the following example:

Work for constant

Recursive

Recursive single

Calls

Parameter: call:

: 1 n/2

Initial n value: 16

Press the Animation button to see the amount of work done.

In this case, only a constant amount of work is done by each recursive call.

However, the number of calls made varies with n, so our total complexity is

not constant. The work fills in a column. The width is 1 and the height is log n

+1. Thus the complexity is O(log n).

Estimate Complexity Using Formula

How to use the applet

First, select parameter values for the code you want to estimate. Several parameters are important:

 Work for a single call

How many recursive calls are made.

The parameter used in recursive calls.

Thus, for the code void doit(int n)

{ if (n<1) return;

for (int i=0; i < n; i++)

x++ ;

doit(n/2);

doit(n/2);

}

The parameters would be: work n two recursive calls n/2 is parameter on recursion

Second , click button "Analyze" to analyze the code using formula. The result will be shown in the Control Options area.

Notice, that using the formulas gives you the exact same answer as you got using the pictorial analysis.

Third : check "Let Me Try" and fill in the values which are needed by the formula

Enter the values for a,b, k and Complexity in the control options section by looking at the code.

a: The numer of recursive calls(calls to doit) in the doit function. b: the divisor on n. For the recursive parameter n/2, this value would be 2. k: the order of work of a single doit call. This would be 1 for a single for loop and 0 if there is no loop at all.

Compare the values of a and b k using the formula and evaluate the big O complexity.

Select it in the drop down. Now press 'Verify'. Step 4: If your answer is incorrect, press 'Check' to see the correct answer.

How do you figure out the complexity from experimental data when you don't even know the constants?

If you are a good guesser: “Eyeball it” to come up with a good guess. Then figure out the constant for one entry. Next, see if that constant works for all the entries. This is basically an “approximate-then-finalize” approach.

How do you guess at the complexity? Guessing is made easier when the values are shown for problem sizes that double (as is the case in our ILM). Then you can look at successive entries to see the pattern.

 O(1) is basically constant between successive entries.

 O(log n) grows slowly - by a constant between entries.A

 O(n) doubles (a factor of 2) between entries.A

 O(n log n) slightly more than doubles between entries.

 O(n 2 ) quadruples (a factor of 4) between entries .

 O(n 2 log n) slightly more than quadruples between entries.

O(n 3 ) entries are growing by a factor of eight.

O(2 n ) grows exponentially.

Download