0% found this document useful (0 votes)
26 views46 pages

Lecture 4_ Recursive Algorithms

Recursive algorithms solve problems by breaking them down into smaller instances of the same problem until reaching a base case that can be solved directly. Key components include identifying base cases, devising a problem-splitting strategy, and combining subproblem results. Recursion is widely used in data structures, sorting algorithms, and artificial intelligence applications, but it may involve overhead due to function calls and stack management.

Uploaded by

mikaye.collins23
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views46 pages

Lecture 4_ Recursive Algorithms

Recursive algorithms solve problems by breaking them down into smaller instances of the same problem until reaching a base case that can be solved directly. Key components include identifying base cases, devising a problem-splitting strategy, and combining subproblem results. Recursion is widely used in data structures, sorting algorithms, and artificial intelligence applications, but it may involve overhead due to function calls and stack management.

Uploaded by

mikaye.collins23
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 46

Design and Analysis of

Algorithms
Recursive algorithms

Department of Computer Science


Recursive definitions
❖A recursive algorithm solves a problem by solving smaller
instances of the same problem.
❖It repeatedly breaks the problem down into simpler
subproblems until it reaches a base case, which can be
solved directly.
❖General Structure:
• Base Case(s): The simple, smallest instance of the
problem which can be solved directly.
• Recursive Case: is defined in terms of itself and must
always move closer to the base case.
❖Applications of Recursion:
Widely used in algorithms that deal with hierarchical
structures (like trees), divide-and-conquer strategies, and
certain mathematical problems.
2
Recursive algorithm

❖A recursive algorithm solves the problem by


possibly using the result of applying itself to a
simpler problem Image:SierpinskiTriangle.PNG

❖Example: Draw this picture

3
General Recursive Design Strategy

❖ Identify the base case(s) (for direct solution)

❖ Devise a problem splitting strategy


 Subproblems must be smaller
 Subproblems must work towards a base case

❖ Devise a solution combining strategy

4
Requirements for Recursive Solution

❖ At least one “small” case that you can solve


directly

❖ A way of breaking a larger problem down into:


 One or more smaller subproblems
 Each of the same kind as the original

❖ A way of combining subproblem results into an


overall solution to the larger problem

5
Recursive Thinking

❖Recursion is:
 A problem-solving approach, that can ...
 Generate simple solutions to ...
 Certain kinds of problems that ...
 Would be difficult to solve in other ways

❖Recursion splits a problem:


 Into one or more simpler versions of itself

6
Recursive Thinking:

❖The General Approach


1. if problem is “small enough”
2. solve it directly
3. else
4. break into one or more smaller
subproblems
5. solve each subproblem recursively
6. combine results into solution to whole
problem
7
Recursive Thinking

Strategy for searching a sorted array:


1. if the array is empty
2. return -1 as the search result (not present)
3. else if the middle element == target
4. return subscript of the middle element
5. else if target < middle element
6. recursively search elements before middle
7. else
8. recursively search elements after the middle

8
Recursive algorithm Properties

❖A recursive algorithm solves the large problem


by using its solution to a simpler sub-problem
 divide and conquer approach

❖Eventually the sub-problem is simple enough


that it can be solved without applying the
algorithm to it recursively
 This is called the ‘base case’

9
Key Components of a Recursive Algorithm
Design
1. What is a smaller identical problem(s)?
Decomposition
2. How are the answers to smaller problems
combined to form the answer to the larger
problem?
Composition
3. Which is the smallest problem that can be solved
easily (without further decomposition)?
Base/stopping case

10
Recursion

❖A recursive procedure can often be analyzed


by solving a recursive equation
❖Basic form:
T(n) = if (base case) then some constant
else ( time to solve subproblems +
time to combine solutions )
❖Result depends upon
 how many subproblems
 how much smaller are subproblems
 how costly it is to combine solutions (coefficients)
11
Example: Factorial Function

❖The factorial function: multiply together all


numbers from 1 to n.
❖denoted n!
n!=n*(n-1)*(n-2)*…2*1

General case: Uses a solution to


n!= n*(n-1)! if n>0 a simpler sub-problem

1 if n==0 Base case: Solution is given


directly

12
public static int factorial(int n)
Execution Trace {
int fact;
if (n > 1) // recursive case (decomposition)
fact = factorial(n – 1) * n; (composition)
(decomposition) else // base case
fact = 1;
return fact;
}

factorial(4)

factorial(3) 4

13
public static int factorial(int n)
Execution Trace {
int fact;
if (n > 1) // recursive case (decomposition)
fact = factorial(n – 1) * n; (composition)
(decomposition) else // base case
fact = 1;
return fact;
}

factorial(4)

factorial(3) 4

factorial(2) 3

14
public static int factorial(int n)
Execution Trace {
int fact;
if (n > 1) // recursive case (decomposition)
fact = factorial(n – 1) * n; (composition)
(decomposition) else // base case
fact = 1;
return fact;
}

factorial(4)

factorial(3) 4

factorial(2) 3

factorial(1) 2

15
public static int factorial(int n)
Execution Trace {
int fact;
if (n > 1) // recursive case (decomposition)
fact = factorial(n – 1) * n; (composition)
(composition) else // base case
fact = 1;
return fact;
}

factorial(4)

*
factorial(3) 4

*
factorial(2) 3

*
factorial(1) ->1 2

16
public static int factorial(int n)

Execution Trace {
int fact;
if (n > 1) // recursive case (decomposition)
fact = factorial(n – 1) * n; (composition)

(composition) else // base case


fact = 1;
return fact;
}

factorial(4)
*
factorial(3) 4

*
factorial(2) ->2 3

17
public static int factorial(int n)
Execution Trace {
int fact;
if (n > 1) // recursive case (decomposition)
fact = factorial(n – 1) * n; (composition)
(composition) else // base case
fact = 1;
return fact;
}

factorial(4)
*
factorial(3) ->6 4

18
public static int factorial(int n)
Execution Trace {
int fact;
if (n > 1) // recursive case (decomposition)
fact = factorial(n – 1) * n; (composition)
(composition) else // base case
fact = 1;
return fact;
}

factorial(4) -> 24

19
Improved factorial Method

public static int factorial(int n)


{
int fact=1; // base case value

if (n > 1) // recursive case (decomposition)


fact = factorial(n – 1) * n; // composition
// else do nothing; base case

return fact;
}

20
Example: Palindrome

❖Describe a palindrome recursively ( a palindrome


is a word that has the same spelling both forward
and backwards e.g. bob)

❖Base case:
 An empty string is a palindrome
 A string of one character is a palindrome
❖Recursive step
 If S is a palindrome, then aSb is also a palindrome if
a=b

21
How Recursion Works

To understand recursion, it's crucial to first grasp how


function calls work in a program:
❖ Suspending Execution: When a function (subroutine)
is called, the current function halts execution.
❖ Control Transfer: The called function takes control of
the program and begins execution.
❖ Returning Control: Once the function completes,
control is returned to the calling function.
❖ State Preservation: Local variables and the execution
point in the calling function must be preserved to
restore the state after the function call finishes.

22
How Recursion Works
❖To do this we use a stack.
❖Before a function is called, all relevant data is
stored in a stackframe.
❖This stackframe is then pushed onto the system
stack.
❖After the called function is finished, it simply pops
the system stack to return to the original state.
❖By using a stack, we can have functions call other
functions which can call other functions, etc.
❖Because the stack is a first-in, last-out data
structure, as the stackframes are popped, the
data comes out in the correct order.
23
Limitations of Recursion

❖Recursive solutions may involve extensive


overhead because they use calls.
❖When a call is made, it takes time to build a
stackframe and push it onto the system stack.
❖Conversely, when a return is executed, the
stackframe must be popped from the stack and the
local variables reset to their previous values – this
also takes time.
❖Every time we make a call, we must use some of
the memory resources to make room for the
stackframe.
24
Uses and Real-Life Applications
❖ Data Structures:
 Binary Trees: Traversing trees (in-order, pre-order, post-order).
 Graphs: DFS is implemented using recursion for exploring graph nodes.
❖ Divide and Conquer:
 Sorting Algorithms: Merge Sort, Quick Sort.
 Search Algorithms: Binary Search, Exponential Search.
❖ Mathematics & Algorithms:
 Combinatorics: Recursive algorithms for generating combinations and
permutations.
 Mathematical Proofs: Proof by induction often uses recursive steps.
❖ Artificial Intelligence:
 Backtracking: Solving puzzles like Sudoku, N-Queens, and Maze-solving.
 Minimax Algorithm: Used in decision-making for game AI (e.g., Chess).
❖ File System Traversal:
 Recursion is used in navigating directories and files in a hierarchical file
system (DFS in filesystem traversal).
25
Recurrences

❖The expression:  c n =1

T ( n) = 
2T  n  + c n  1
  2 
is a recurrence.
 Recurrence: an equation that describes a

function in terms of its value on smaller functions


❖A recurrence relation is an equation that
recursively defines a sequence, where each term
is a function of the previous terms.

26
Recurrence Examples

 0 n=0  0 n=0
s ( n) =  s ( n) = 
c + s(n − 1) n  0 n + s (n − 1) n  0

n =1 
 c  c n =1
 
T ( n) =  T ( n) = 
2T   + c n  1
 n  n
  2  aT   + cn n  1
 b
27
Solving Recurrences

❖Recurrences can be solved by the following


methods
 Substitution method

 Iteration method

 Master method

 Recursive tree method

28
The substitution method

❖A.k.a. the “making a good guess method”


❖Guess the form of the answer, then use induction
to find the constants and show that solution works

❖Examples:
 T(n) = 2T(n/2) + (n) → T(n) = (n lg n)

 T(n) = 2T(n/2) + n → T(n) = (n lg n)

 T(n) = 2T(n/2+ 17) + n → (n lg n)

29
The Iteration method

❖Another option for solving recurrences the


“iteration method”
 Expand the recurrence

 Work some algebra to express as a summation

 Evaluate the summation

30
The Iteration method

❖ T(n) =  c n =1
 n
2T(n/2) + c T (n) = 2T
  + c n 1
2(2T(n/2/2) + c) + c   2 
22T(n/22) + 2c + c
22(2T(n/22/2) + c) + 3c
23T(n/23) + 4c + 3c
23T(n/23) + 7c
23(2T(n/23/2) + c) + 7c
24T(n/24) + 15c

2kT(n/2k) + (2k - 1)c

31
The Iteration method

❖So far for n > 2k we have


k k k
 T(n) = 2 T(n/2 ) + (2 - 1)c

❖Determine the value of 𝑘: The recursion continues


until 𝑛/2𝑘=1, which happens when 𝑘=log2(𝑛).
Therefore, at this point:
 T(n) = 2
lg n T(n/2lg n) + (2lg n - 1)c

= n T(n/n) + (n - 1)c Note: 2 lg n=n

= n T(1) + (n-1)c
= nc + (n-1)c = (2n - 1)c  c n =1
 n
T (n) = 2T
  + c n 1
  2 
32
Proving a Recursive Method
Correct
Recall Proof by Induction:
1. Prove the theorem for the base case(s): n=0
2. Show that:
▪ If the theorem is assumed true for n,
▪ Then it must be true for n+1

Result: Theorem true for all n ≥ 0.

33
Proving a Recursive Method Correct

Recursive proof is similar to induction:


1. Show base case recognized and solved
correctly
2. Show that
▪ If all smaller problems are solved correctly,
▪ Then original problem is also solved
correctly
3. Show that each recursive case makes
progress towards the base case 
terminates properly

34
Recursive Versus Iterative
Methods

All recursive algorithms/methods


can be rewritten without recursion.

❖Iterative methods use loops instead of recursion

❖Iterative methods generally run faster and use


less memory--less overhead in keeping track of
method calls

35
Recursion Versus Iteration

❖Recursion and iteration are similar


❖Iteration:
 Loop repetition test determines whether to exit
❖Recursion:
 Condition tests for a base case
❖Can always write iterative solution to a
problem solved recursively, but:
❖Recursive code often simpler than iterative
 Thus easier to write, read, and debug
36
Efficiency of Recursion

❖Recursive method often slower than iterative;


why?
 Overhead for loop repetition smaller than
 Overhead for call and return
❖If easier to develop algorithm using recursion,
 Then code it as a recursive method:
 Software engineering benefit probably outweighs
...
 Reduction in efficiency
❖Don’t “optimize” prematurely!
37
So When Should You Use Recursion?

❖Solutions/algorithms for some problems are


inherently recursive
 iterative implementation could be more
complicated
❖When efficiency is less important
 it might make the code easier to understand

❖Bottom line is about:


 Algorithm design
 Tradeoff between readability and efficiency
38
Towers of Hanoi: Description

Goal: Move entire tower to another peg


Rules:
1. You can move only the top disk from a peg.
2. You can only put a smaller on a larger disk
(or on an empty peg)

39
Towers of Hanoi: Solution Strategy

40
Towers of Hanoi: Solution Strategy

41
Towers of Hanoi: Recursion Structure

move(n, src, dst, tmp) =


if n == 1: move disk 1 from src to dst
otherwise:
move(n-1, src, tmp, dst)
move disk n from src to dst
move(n-1, tmp, dst, src)

42
Computing Powers

❖The power function, p(x,n)=xn, can be defined


recursively:
 1 if n = 0
p ( x, n ) = 
 x  p( x, n − 1) else
❖This leads to a power function that runs in O(n)
time (for we make n recursive calls).
❖We can do better than this, however.

43
Recursive Squaring

❖We can derive a more efficient linearly recursive


algorithm by using repeated squaring:

 1 if x = 0

p( x, n) =  x  p( x, (n − 1) / 2) if x  0 is odd
2

 p ( x , n / 2) 2
if x  0 is even

❖For example,
24 = 2(4/2)2 = (24/2)2 = (22)2 = 42 = 16
25 = 21+(4/2)2 = 2(24/2)2 = 2(22)2 = 2(42) = 32
26 = 2(6/ 2)2 = (26/2)2 = (23)2 = 82 = 64
27 = 21+(6/2)2 = 2(26/2)2 = 2(23)2 = 2(82) = 128. 44
Analyzing the Recursive Squaring
Method

Algorithm Power(x, n):


Input: A number x and
integer n = 0
Output: The value xn Each time we make a
recursive call we halve the
if n = 0 then value of n; hence, we make
return 1 log n recursive calls. That
if n is odd then is, this method runs in
y = Power(x, (n - 1)/ 2) O(log n) time.
return x · y · y
else It is important that we
used a variable twice
y = Power(x, n/ 2)
here rather than calling
return y · y the method twice.
45
Challenges of Recursion
❖ Stack Overflow:
 Each recursive call consumes stack space. If the recursion depth is too

large, it can lead to a stack overflow error.


 Solution: Tail recursion optimization (or converting to an iterative
solution).
❖ Efficiency:
 Recursive algorithms can have redundant calculations;

 Solution: Memoization or dynamic programming.

❖ Memory Usage:
 Each call adds a new layer to the call stack, which can increase memory

usage.
 Solution: Use iterative solutions where possible or optimize recursion.

❖ Debugging:
 Can be difficult to debug when there are multiple recursive calls.

 Solution: Add proper base cases and use debugging tools (or print

statements) to trace recursion steps.


46

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy