Title: Recursive algorithms
1Recursive algorithms
- Recursive solution solve a smaller version of
the problem and combine the smaller solutions. - Example to find the largest element in an array
A1..n - If n is 1, the problem is easily solvable. Just
return An - If ngt1, then find the largest element of
A1..n-1, compare it to An and return the
largest.
2Recursive algorithms
- Recursive solutions consist of
- Base case(s)
- The problem is explicitly solved for certain
values of the input (generally small values) - Recursive step
- Divide the problem into one or more simpler or
smaller parts. - Solve each part recursively
- Combine the solutions of the parts into a
solution to the problem
IMPORTANT! If the "part" is as big as the whole,
then your program will not terminate
IMPORTANT! If this is missing, or not implemented
correctly, your program will not terminate.
3Recursive algorithms
- Rules for successful recursion
- Handle the base case(s) first
- Make sure that the recursive step is applied on a
smaller version of the problem. - "smaller" means closer to the base case
- But not too close, too fast. Make certain that
the base case will be reached.
4Recursive procedures
- Pros
- Often intuitive, more elegant
- Result in shorter programs
- Sometimes, a recursive solution may result in a
faster algorithm - Usually easier to prove correctness
- Cons
- More overhead due to function calls
- More memory used at runtime
- Sometimes, not as fast as an iterative solution
to the problem
5Recursive procedures
- Any problem that can be solved recursively can be
solved iteratively - Choose recursion when
- you have a recursive data structure
- the recursive solution is easier to
understand/debug - Do not choose recursion when
- performance is an issue
- Examples where recursion is better
- Towers of Hanoi, certain sorting algorithms
6Recursive definitions
- list
- NULL (empty list, base case)
- a node followed by a list
- Example
- is a list (the empty list)
- is a list (c node followed by a
list) - is a list (b node followed by a
list) - is a list (a node
followed by a list)
NULL
NULL
NULL
NULL
7Time Analysis
- A recursive algorithm contains a call to itself.
- Computing the running time of a recursive
algorithm involves solving a recurrence equation
one that describes the running time in a
recursive manner. - We will describe the process through an example
8The Binary Search Algorithm
Input Sorted array A of size n, target
element Output If target is in A, its index,
else -1 BinarySearch(A, left, right, target) //
initially left0, right N-1 int
BinarySearch(int A , int left, int right, int
target) if (left right) if
(Aleft target) return left
else return 1 int mid
(leftright)/2 if (Amid gt target)
return BinarySearch(A, left, mid-1, target)
else return BinarySearch(A, mid1, right,
target)
9The Binary Search Algorithm
int BinarySearch(int A , int left, int right,
int target) if (left right) if
(Aleft target) return left
else return 1 int mid
(leftright)/2 if (Amid gt target)
return BinarySearch(A, left, mid-1, target)
else return BinarySearch(A, mid1,
right, target)
Constant time operations. Their duration is
always the same regardless of n's value.
How long would this take?
10The Binary Search Algorithm
- Let T(n) be the time it takes to run Binary
Search on an array of size n. - Then T(n) is equal to
- the (constant) time it takes to check the base
case and compute mid, - plus the time it takes to run Binary Search on
one half of the array. - In other words,
- T(n) 1 T(n/2)
11Time Analysis
- For Binary Search we got the recurrence equation
T(n) 1 T(n/2) - One way to solve this is by substitution
- T(n) 1 T(n/2)
- T(n/2) 1 T(n/4)
- T(n/4) 1 T(n/8)
- etc.
12Time Analysis
- T(n) 1 T(n/2)
- 1 ( 1 T(n/4) ) 2 T(n/22)
- 2 ( 1 T(n/8) ) 3 T(n/23)
- ... i T(n/2i)
- What does this represent so far?
- At step i, the time it has taken to search an
array of size n is equal to i plus the time to
search an array of size n/2i
13Time Analysis
- T(n) 1 T(n/2)
- 1 ( 1 T(n/4) ) 2 T(n/22)
- 2 ( 1 T(n/8) ) 3 T(n/23)
- ... i T(n/2i)
- When do we stop substituting?
- In the worst case, we'll keep going until we
reach the base case. - In other words, we'll stop when the subarray
we're searching has size 1. - This means that when we stop, n/2i 1
14Time Analysis
- T(n) i T(n/2i)
- When do we stop substituting?
- We stop when n/2i 1 ? i logn
- After logn steps (in the worst case), we have
reached the base case, which is an array of size
1. - Then, in one step, we decide whether the element
is found or not.
15Time Analysis
- In the end,
- T(n) i T(n/2i) logn T(1)
logn 1 ?(logn) - Notes
- An iterative version of Binary Search would run
in ?(logn) as well, but would be a better choice
in practice - Less space (just an extra local variable)
- Less time in absolute terms (no function calls)