CSE 326 Analyzing Recursion David Kaplan Dept of Computer Science & Engineering Autumn 2001
Analyzing RecursionCSE 326 Autumn Recursion Rules Rules for using recursion effectively (Weiss 1.3): 1. Base cases Must have some non-recursive base case(s). 2. Making progress Recursive call must progress toward a base case. 3. Design rule Assume the recursive calls work. 4. Compund interest rule Don’t duplicate work in separate recursive calls.
Analyzing RecursionCSE 326 Autumn Recurrence Equations A recursive procedure can often be analyzed by solving a recurrence equation of the form: T(n) = base case: some constant recursive case: T(subproblems) + T(combine) Result depends upon how many subproblems how much smaller are subproblems how costly to combine solutions (coefficients)
Analyzing RecursionCSE 326 Autumn Example: Sum of Queue SumQueue(Q) if (Q.length == 0 ) return 0 else return Q.dequeue() + SumQueue(Q) One subproblem Linear reduction in size (decrease by 1) Combining: constant (cost of 1 add) T(0) b T(n) c + T(n – 1) for n>0
Analyzing RecursionCSE 326 Autumn Sum of Queue Solution T(n) c + c + T(n-2) c + c + c + T(n-3) kc + T(n-k) for all k nc + T(0) for k=n cn + b = O(n) T(0) b T(n) c + T(n – 1) for n>0 Equation: Solution:
Analyzing RecursionCSE 326 Autumn Example: Binary Search BinarySearch(A, x) if (A.size == 1) return (x == A[0]) mid = A.size / 2 if (x == A[mid]) return true else if (x < A[mid]) return BinarySearch( A_LowerHalf, x) else if (x > A[mid]) return BinarySearch( A_UpperHalf, x) T(1) b T(n) T(n/2) + c for n>1 Equation: Search a sorted array for a given item, x If x == middle array element, return true Else, BinarySearch lower (x mid) sub-array 1 subproblem, half as large
Analyzing RecursionCSE 326 Autumn Binary Search: Solution T(n) T(n/2) + c T(n/4) + c + c T(n/8) + c + c + c T(n/2 k ) + kc T(1) + c log n where k = log n b + c log n = O(log n) T(1) b T(n) T(n/2) + c for n>1 Equation: Solution:
Analyzing RecursionCSE 326 Autumn Recursion Tree for Binary Search n n/2 n/4 … 1 O(1) … log n Θ(log n) O(1) Problem sizeCost per stage
Analyzing RecursionCSE 326 Autumn Example: MergeSort Split array in half, sort each half, merge sub-arrays 2 subproblems, each half as large linear amount of work to combine T(n) 2T(n/2)+cn 2(2(T(n/4)+cn/2)+cn = 4T(n/4) +cn +cn 4(2(T(n/8)+c(n/4))+cn+cn = 8T(n/8)+cn+cn+cn 2kT(n/2k)+kcn 2kT(1) + cn log n where k = log n = O(n log n)
Analyzing RecursionCSE 326 Autumn Recursion Tree for Merge Sort n n/2 n/4 ……… 111 O(n) … log n Θ(n log n) Problem sizeCost per stage
Analyzing RecursionCSE 326 Autumn Example: Recursive Fibonacci Fibonacci numbers seems like a great use of recursion Simple, elegant-looking recursive code … Fibonacci(i) if (i == 0 or i == 1) return 1 else return Fibonacci(i - 1) + Fibonacci(i - 2)
Analyzing RecursionCSE 326 Autumn Fibonacci Call Tree Fib(5) Fib(4) Fib(3) Fib(2) Fib(3) Fib(1) Fib(0) Fib(1) Fib(2) But what actually happens is combinatorial explosion
Analyzing RecursionCSE 326 Autumn Analyzing Recursive Fibonacci Running time: Lower bound analysis T(0), T(1) 1 T(n) T(n - 1) + T(n - 2) + c if n > 1 Note: T(n) Fib(n) Weiss shows in that Fib(n) < (5/3) n Similar logic shows that Fib(n) (3/2) n for N>4 In fact: Fib(n) = ((3/2) n ), Fib(n) = O((5/3) n ), Fib(n) = θ( n ) where = (1 + 5)/2
Analyzing RecursionCSE 326 Autumn Non-Recursive Fibonacci Avoid recursive calls Keep a table of calculated values each time you calculate an answer, store it in the table Before performing any calculation for a value n check if a valid answer for n is in the table if so, return it Memoization a form of dynamic programming How much time does memoized Fibonacci take?