[Instructions] [Search] [Current] [Syllabus] [Links] [Handouts] [Outlines] [Labs] [More Labs] [Assignments] [Quizzes] [Examples] [Book] [Tutorial] [API]

**Assigned**: Friday, February 26, 1999

**Due**: Monday, March 8, 1999

In this assignment, you will apply, explore, and expand your skills at algorithm design and analysis.

One of the reasons that computer scientists developed a formal description
of Big-O is that it permits us to develop and apply a number of important
identities. For example, we might wish to consider whether BigO is
transitive. That is, if f(N) is in O(g(n)) and g(n) is in O(h(n)),
can we say that f(N) is in O(h(n))?^{1}

We've said that Big-O notation allows us to discard lower-order terms. Let's try to formalize that idea. Prove that if f(N) is in O(g(N)+h(N)), and g(N) is in O(h(N)), then f(N) is in O(h(N)).

We've said that Big-O notation allows us to discard constant multipliers. Let's try to formalize that idea. Prove that if f(N) is in O(C*g(N)) then f(N) is in O(g(N)).

We've done some exploring of the Fibonacci sequence, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ..., which might be defined by the following Java function.

/** * Compute the nth Fibonacci number. * Pre: n >= 0 * Pre: the nth Fibonacci number <= Long.MAX_VALUE * Post: returns the nth Fibonacci number */publiclongfib(longn) {if(n <= 1)returnn;elsereturnfib(n-1) + fib(n-2); } // fib(long)

Compute upper and lower bounds on the running time of the definition of
`fib`

given above. Express the running time in Big-O notation,
in terms of the
number of calls to `fib`

in order to compute `fib(n)`

.
The bounds should be as tight as you can
get them (preferably, both will be the same).

Hint: you can assume that the number of steps to compute fib(n) is at least as many as the number to compute fib(n-1).

Improve the computation of the nth Fibonacci number using the technique of dynamic programming (caching previously computed results in a table). Test your revised function appropriately.

Compute an upper bound on the running time for your new method of computing
the Fibonacci numbers. Express the running time in Big-O notation,
in terms of the
number of calls to `fib`

in order to compute `fib(n)`

.
The bound should be as tight as you can
get it.

Rewrite your efficient Fibonacci computer iteratively (using loops rather than recursion).

Theodore and Themla Trinary enjoyed the use of binary search so much that they've decided to develop their own variant, based on dividing the subarray into three parts, rather than two. Here's their algorithm.

/** * Determine the index of x in array A. * Pre: A is sorted in increasing order. * Post: If x is in A, then returns i s.t. A[i] == x * Post: If x is not in A, then throws an exception */publicinttrinarySearch(intx,int[] A)throwsException {// Use the marvelous helper functionreturntrinarySearch(x, A, 0, A.length-1); } // trinarySearch(int, int[])/** * Determine the index of x in the subarray of A given by lb..ub. * Pre: A is sorted in increasing order. * Pre: If x is in A, then x is in the subarray. * Pre: If x is not in A, then x is not in the subarray. * Post: If x is in A, then returns i s.t. A[i] == x * Post: If x is not in A, then throws an exception */publicinttrinarySearch(intx,int[] A,intlb,intub)throwsException {// Base case: empty subarray. x is not in A.if(ub < ub)thrownewException("Not found");// Base case: single-element subarray. See if x is that element.elseif(lb == ub) {if(x == A[lb])returnlb;elsethrownewException("Not found"); } // single-element subarray// Recursive cases: split the array and search the appropriate subarray.else{// The first split point is one-third of the way from lb to ub. We// compute the distance from lb to ub, take 1/3 of that, and add it// to lb.intsplitOne = lb + 1/3 * (ub-lb);// The second split point is two-thirds of the way from lb to ub. We// compute the distance from lb to ub, take 2/3 of that, and add it// to lb.intsplitTwo = lb + 2/3 * (ub-lb);// Recursive case: in the first third of the array.if(x <= splitOne)returntrinarySearch(x, A, lb, splitOne);// Recursive case: in the second third of the array.elseif(x < splitTwo)returntrinarySearch(x, A, splitOne+1, splitTwo-1);// Recursive case: in the third third of the array.elsereturntrinarySearch(x, A, splitTwo, ub); } } // trinarySearch(int, int[], int, int)

Unfortunately, their code is riddled with errors. Identify and correct the errors, both syntactic and semantic. If you use a test suite to identify the errors, please include the test suite.

Find a tight upper bound on the running time of the working trinary search, using Big-O notation.

**Endnotes**

^{1} The answer is yes. Here's
a proof.

- Because f(N) is in O(g(N)), there exist N
_{1}and D_{1}such that for all N > N_{1}, |f(N)| <= |D_{1}*g(N)| - Because g(N) is in O(h(N)), there exist N
_{2}and D_{2}such that for all N > N_{2}, |g(N)| <= |D_{2}*h(N)| - Let N
_{3}= max(N_{1}, N_{2}) - Let D
_{3}= max(1,D_{1}) * max(1,D_{2}) - Then for all N > N
_{3}, |f(N)| <= |D_{1}*g(N)| (by the first rule and the definition of N_{3}) - Then for all N > N
_{3}, |g(N)| <= |D_{2}*h(N)| (by the second rule and the definition of N_{3}) - Then for all N > N
_{3}, |D_{1}*g(N)| <= |D_{1}*D_{2}*h(N)| (since D_{1}> 0, we can safely multiply both sides of an inequality for D_{1}without affecting the inequality) - Then for all N > N
_{3}, |f(N)| <= |D_{1}*D_{2}*h(N)| (plug together various inequalities using transitivity of inequality) - Then for all N > N
_{3}, |f(N)| <= |D_{3}*h(N)| (D_{3}>= D_{1}*D_{2}) - Hence f(N) is in O(h(N)) by the definition of Big-O.

[Instructions] [Search] [Current] [Syllabus] [Links] [Handouts] [Outlines] [Labs] [More Labs] [Assignments] [Quizzes] [Examples] [Book] [Tutorial] [API]

**Disclaimer** Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.

This page may be found at http://www.math.grin.edu/~rebelsky/Courses/CS152/99S/Assignments/assign.06.html

Source text last modified Tue Mar 2 08:37:08 1999.

This page generated on Wed Mar 3 09:24:56 1999 by SiteWeaver. Validate this page's HTML.

Contact our webmaster at rebelsky@math.grin.edu