Recursion
• When a method calls itself
• Used to break down a bigger problem into
sub-problems (smaller version of big problem)
• Examples
– Binary Search
– Fibonacci
Binary Search
• Find an element in a sorted array
– Array must be sorted
– Element does not have to exist in the array
• Main steps
– Divide – Compare the value to the middle element
– Conquer – Recursively search one half of the array
Binary Search Example
Looking for value: 7
Binary Search Example
Looking for value: 7
2 3 5 7 11 13 17 19 23
Compare 7 to 11
Binary Search Example
Looking for value: 7
2 3 5 7 11 13 17 19 23
Compare 7 to 3
Binary Search Example
Looking for value: 7
2 3 5 7 11 13 17 19 23
Compare 7 to 5
Binary Search Example
Looking for value: 7
2 3 5 7 11 13 17 19 23
Recursive Binary Search Java Code
public static int recursiveBinarySearch(int value, int[] someArray, int min, int max){ int mid = (min + max) / 2;
if(someArray[mid] == value){ return mid;
}
else if(mid == 0 || mid == someArray.length-1){ return -1;
}
else if(value > someArray[mid]){
return recursiveBinarySearch(value, someArray, mid+1, max); }
else if(value < someArray[mid]){
return recursiveBinarySearch(value, someArray, min, mid-1); }
Iterative Binary Search Java Code
public static int iterativeBinarySearch(int value, int[] someArray){int position = -1; int min = 0;
int max = someArray.length-1; int mid = (min + max) / 2; int lastMid = -1;
while(position == -1 && mid != lastMid){ if(someArray[mid] == value){
position = mid; }
else if(value > someArray[mid]){ lastMid = mid;
min = mid+1;
mid = (min + max) / 2; }
else if(value < someArray[mid]){ lastMid = mid;
max = mid-1;
Recursion vs Iteration
• It has been proven anything done recursively
can also be done iteratively
• Iteration is faster than recursion
– When the depth of the recursion is deep
– Save time on the function call stack
• An algorithm may be easier to write
recursively
Recursive to Iterative Conversion Tips
• You will likely need to replace the recursive
call with a loop
• Some recursive algorithms have loops in them
– You will likely need to replace with nested loops
• You may have to implement your own Stack
– Depends on what values need to be remembered
– If needed this makes the conversion much harder
Iterative to Recursive Conversion Tips
• Try replacing loops with recursive calls
• May need to pass parameters to the function
– Depends on what values you need to remember
• Turn base cases into return statements with a
hardcoded value
• Non-base cases should be turned into recursive
Recursion Base Cases
• Don’t forget all base cases
– Prevent infinite recursion
– Prevent exceptions on some input values
• Most functions have more than 1
– The obvious one
– The one for edge case input values
"Helper Function"
• It's often cleaner and more convenient to
separate argument checking in one method and recursion / computation in another
• Ex: Merge Sort
• Recursive function for break down logic
– Ex: Breaking down into subsists
• Non-recursive function for problem logic
Fibonacci
• Fibonacci sequence
– undefined for n < 0
– f(0) = 0
– f(1) = 1
Fibonacci Sequence
Fibonacci
• Fibonacci sequence
– undefined for n < 0
– f(0) = 0 = BASE CASE
– f(1) = 1 = BASE CASE
– f(n) = f(n-1) + f(n-2) for n > 1
Recursive Fibonacci Java Code
public static long recursiveFibonacci(long n) {
if(n == 0) {
return 0l; }
else if(n == 1) {
return 1l; }
else {
Iterative Fibonacci Java Code
public static long iterativeFibonacci(long n) {
long previous2 = 0; long previous1 = 1; long total = 0;
for(long i=1; i<n; i++) {
total = previous1 + previous2; previous2 = previous1;
previous1 = total; }
if(n == 1) {
Factorial
• Factorial
– undefined for n < 0
– f(0) = 1 = BASE CASE
– f(1) = 1 = BASE CASE
– f(n) = n * f(n-1) for n > 1
Factorial
n 0 1 2 3 4 5 6 7 8
Recursive Factorial Java Code
public static long recursiveFactorial(long n) {
if(n == 0) {
return 1l; }
else if(n == 1) {
return 1l; }
else {
Iterative Factorial Java Code
public static long iterativeFactorial(long n) {
long result = 1;
for(long i=0; i<n; i++) {
result = result * (n-i); }
Recurrence Relation
• A recurrence relation can be used to analyze a
recursive algorithm
Recurrence Relation
• General form
– T(n) = a T(n/b) + f(n)
– a = number of sub problems split into
• a > 1
– n = input size
– b > 1
– n/b = sub problem size
Recurrence Relation Example
T(n) = 2 T(n/2) + O(n)
# subproblems
subproblem size
Recursion-tree method
• A recursion tree models the costs (time) of a
recursive execution of an algorithm.
• The recursion tree method is good for
generating guesses for the substitution method.
Recursion Tree
• To evaluate the total cost of the recursion tree
– sum all the non-recursive costs of all nodes
– = Sum (rowSum(cost of all nodes at the same depth))
• Determine the maximum depth of the recursion tree:
– For our example, at tree depth d the size parameter is n/(2d)
– the size parameter converging to base case, i.e. case 1 – such that, n/(2d) = 1,
– d = lg(n)
Example of recursion tree
Example of recursion tree
T(n)
Example of recursion tree
T(n/4) T(n/2)
n2
Example of recursion tree
Solve T(n) = T(n/4) + T(n/2) + n2:
n2
(n/4)2 (n/2)2
Example of recursion tree
(n/16)2 (n/8)2 (n/8)2 (n/4)2 (n/4)2 (n/2)2
Q(1) …
Solve T(n) = T(n/4) + T(n/2) + n2:
Example of recursion tree
Solve T(n) = T(n/4) + T(n/2) + n2:
(n/16)2 (n/8)2 (n/8)2 (n/4)2 (n/4)2 (n/2)2
Q(1) …
Example of recursion tree
Solve T(n) = T(n/4) + T(n/2) + n2:
(n/16)2 (n/8)2 (n/8)2 (n/4)2 (n/4)2 (n/2)2
Q(1) …
n2
2 165 n
2
Example of recursion tree
Solve T(n) = T(n/4) + T(n/2) + n2:
(n/16)2 (n/8)2 (n/8)2 (n/4)2 (n/4)2
Q(1) …
n2
(n/2)2
…
2 165 n
2
n
Example of recursion tree
Solve T(n) = T(n/4) + T(n/2) + n2:
(n/16)2 (n/8)2 (n/8)2 (n/4)2 (n/4)2
Q(1)
… …
Total =
n2
(n/2)2 2
165 n 2
n
2 25625 n
1 5 5 2 5 3
Binary Search
Recurrence for binary search
T(n) = ? T(?) + Q(?)
# subproblems
subproblem size
Recurrence for binary search
T(n) = 1 T(n/2) + Q(1)
# subproblems
subproblem size