0% found this document useful (0 votes)
5 views29 pages

Recursion and Divide & Conquer Methods

Uploaded by

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

Recursion and Divide & Conquer Methods

Uploaded by

kritikapalli17
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd

Today’s Material

• Recursion & Recursive Functions


– Divide & Conquer as an algorithm design strategy
– How to implement divide & conquer algorithms using recursion
Recursive Functions
• It is possible for a function to call itself
– Called a recursive function
– Some problems are very easily solved using recursion

• The strategy by which recursion is used to solve a problem


is called divide-and-conquer
Divide & Conquer Strategy (1)
• Divide the problem into smaller problems of the same type (divide)
• Solve each subproblem recursively using the same algorithm
(conquer)
• Merge the solutions to subproblems to obtain the solution for the
original problem
P

P1 ...................
P2 Pn
......

P1 P1 ... P1 P2 P2 ... P2n Pn Pn ... Pn


1 2 n 1 2 1 2 n

.................................................................................................................
...............................
Cases
Base

P P P P P P P P P ................ P P P
Divide & Conquer Strategy (2)
/* Solve a problem P */
Solve(P){
/* Base case(s) */
if P is a base case problem
return the solution immediately

/* Divide P into P1, P2, ..Pn each of smaller scale (n>=2) */


/* Solve subproblems recursively */
S1 = Solve(P1); /* Solve P1 recursively to obtain S1 */
S2 = Solve(P2); /* Solve P2 recursively to obtain S2 */

Sn = Solve(Pn); /* Solve Pn recursively to obtain Sn */

/* Merge the solutions to subproblems */


/* to get the solution to the original big problem */
S = Merge(S1, S2, …, Sn);

/* Return the solution */


return S;
} //end-Solve
Computing 1+2+..+N Recursively
• Compute the sum of the numbers from 1 to n:
– Sum(n) = 1+2+3+..+n

• Base case
– If n = 1, then Sum(1) = 1

• Recursive Formulation:
– Sum(n) = 1+2+…+(n-1) + n
– Sum(n) = Sum(n-1) + n
Computing 1+2+..+N Recursively
[Link]

/* Computes 1+2+3+…+n */ int main(){


int sum(int n){ int x = 0;
/* Base case */
if (n == 1) return 1; x = sum(4);
cout << x << endl;
/* Divide and conquer */
int partialSum = sum(n-1); return 0;
} /* end-main */
/* Merge */
return partialSum + n;
} /* end-sum */
Recursion Tree for Sum(4)
[Link]
main
/* Computes 1+2+3+…+n */
x=sum(4) =1
int sum(int n){
0
/* Base case */
sum(4) return 6+4
if (n == 1) return 1;
partialSum=sum(3) =
/* Divide and conquer */ 6
int partialSum = sum(n-1);
return 3+3
sum(3)
/* Merge */
return partialSum + n; partialSum=sum(2) =
} /* end-sum */ 3
return 1+2
sum(2)
main(){
int x = sum(4); partialSum=sum(1) =
cout << “Sum: “ << x << endl; 1
} /* end-main */
sum(1)
return 1
Call Stack for Sum(4)
[Link]
/* Computes 1+2+3+…+n */
Stack
int sum(int n){
/* Base case */ x = sum(4) =10 main
if (n == 1) return 1; n=4
Sum(4)
partialSum = sum(3) =6
/* Divide and conquer */
int partialSum = sum(n-1); n=3
Sum(3)
partialSum = sum(2) =3
/* Merge */
n=2
return partialSum + n; Sum(2)
} /* end-sum */ 1
partialSum = sum(1) =
n=1
Sum(1)
main(){ partialSum
int x = sum(4);
cout << “Sum: “ << x << endl;
} /* end-main */
Computing N! Recursively
• Consider the problem of computing n! = 1*2*3*…*n

• Base cases
– If n = 0, then Factorial(0) = 1
– If n = 1, then Factorial(1) = 1

• Recursive Formulation:
– Factorial(n) = 1*2*…*(n-1)*n
– Factorial(n) = Factorial(n-1)*n
Computing N! Recursively
[Link]
/* Computes 1*2*3*..*n */ int main(){
int factorial(int n){ int x = 0;
/* Base cases */
if (n <= 1) return 1; // 0!=1!=1 x = factorial(4);
cout << x << endl;
/* Divide and conquer */
int partialAns = factorial(n-1); return 0;
} /* end-main */
/* Merge */
return partialAns*n;
} /* end-factorial */
Recursion Tree for factorial(4)
[Link] main
/* Computes 1*2*3*..*n */ factorial(4) =2
int factorial(int n){ 4
/* Base cases */
if (n <= 1) return 1; // 0!=1!=1 factorial(4) return 6*4
partialAns=factorial(3)=
/* Divide and conquer */ 6
int partialAns = factorial(n-1); return 2*3
factorial(3)
/* Merge */ partialAns=factorial(2)=
return partialAns*n; 2
} /* end-factorial */ return 1*2
factorial(2)
main(){
cout << factorial(4) << endl; partialAns=factorial(1)=
1
} /* end-main */
factorial(1)
return 1
Call Stack for factorial(4)
[Link]
/* Computes 1*2*3*..*n */ Stack
int factorial(int n){
/* Base cases */ factorial(4) =24 main
if (n <= 1) return 1; // 0!=1!=1 n=4
factorial(4)
/* Divide and conquer */ partialAns = factorial(3) =6
int partialAns = factorial(n-1); n=3
factorial(3)
partialAns = factorial(2) =2
/* Merge */
n=2
return partialAns*n; factorial(2)
} /* end-factorial */ 1
partialAns = factorial(1) =
n=1
main(){ factorial(1)
partialAns
cout << factorial(4) << endl;
} /* end-main */
Printing a Triangle Recursively (1)
• Consider the problem of printing a triangle with “n” rows
– Here is a triangle with 7 rows

• Base Case
– Print nothing if n <= 0

Triangle • Recursive Formulation


with n-1
rows – Print a triangle with “n-1” rows
– Then print the last row with “n” star
chars
Printing a Triangle Recursively (2)
[Link]

triangle(5) *****

triangle(4) ****

triangle(3) ***

triangle(2) **

triangle(1) *

triangle(0)
Finding the first digit of a number (1)
• You are given a positive integer “n”
• Write a recursive function to return the first digit of the
number
– firstDigit(34257)  3
– firstDigit(8)  8

• Base case
– if n <= 9, return n

• Recursive Formulation
– Peel off the last digit of “n” and recursively find the first digit of the
remaining number -> return firstDigit(n/10)
– firstDigit(654) -> firstDigit(65) -> firstDigit(6)  return 6
Finding the first digit of a number (2)
[Link] return 4

firstDigit(456385)
return 4

firstDigit(45638)
return 4

firstDigit(4563)
return 4

firstDigit(456)
return 4

firstDigit(45)
return 4
firstDigit(4)
Counting the number of digits of a number
(1)
• You are given a positive integer “num”
• Write a recursive function to count the number of digits in
num
– numDigits(34257)  5
– numDigits(8) -> 1

• Base case
– if n <= 9, return 1

• Recursive Formulation
– Count the number of digits in n/10 and add 1 to it
Counting the number of digits of a number
(2)
[Link] return 6

numDigits(456385)
return 5

numDigits(45638)
return 4

numDigits(4563)
return 3

numDigits(456)
return 2

numDigits(45)
return 1
numDigits(4)
Counting the number of even digits of a
number (1)
• You are given a positive integer “num”
• Write a recursive function to count the number of even digits
in num
– numEvenDigits(34257)  2
– numEvenDigits(8) -> 1
– numEvenDigits(153) -> 0

• Base case
– if n <= 9, return 1 if n%2 == 0 else return 0;

• Recursive Formulation
– Count the number of even digits in n/10. If the last digit is even, add 1
to it
Counting the number of even digits of a number
(2)
[Link]
return 3
numEvenDigits(456385)
return 3

numEvenDigits(45638)
return 2

numEvenDigits(4563)
return 2

numEvenDigits(456)
return 1

numEvenDigits(45)
return 1
numEvenDigits(4)
Range Sum of Numbers (1)
• Consider the problem of computing the sum of the numbers
from x to y, where x <= y
– int rangeSum(int x, int y)

– rangeSum(5, 7): 5+6+7 = 18


– rangeSum(10, 15): 10+11+12+13+14+15 = 75
– rangeSum(20, 20): 20
– rangeSum(21, 20): 0
Range Sum of Numbers (2)
• Base cases:
– x > y  return 0
– x == y  return x

• Recursive Formulations:
1. RangeSum(x, y)x + RangeSum(x+1, y)

2. RangeSum(x, y)RangeSum(x, y-1) + y

3. RangeSum(x, y):
• int middle = x+(y-x)/2;
• RangeSum(x, middle) + RangeSum(middle+1, y)
Range Sum of Numbers (3)
[Link] [Link]

[Link]
Recursion Tree for RangeSum3(3,9)
42

RS3(3,9)
24

18
RS3(3,6) RS3(7,9)
1 9
7 1 15
RS3(3,4) RS3(5,6) RS3(7,8) RS3(9,9)

4 6 8
3 5 7

RS3(3,3) RS3(4,4) RS3(5,5) RS3(6,6) RS3(7,7) RS3(8,8)


Fibonacci Numbers
• Fibonacci numbers are defined as
follows
– F(0) = 0
– F(1) = 1
– F(n) = F(n-1) + F(n-2)
[Link]
/* Computes nth Fibonacci number */
int fibonacci(int n){
/* Base cases */
if (n == 0) return 0;
if (n == 1) return 1;

return fibonacci(n-1) + fibonacci(n-2);


} /* end-fibonacci */
Recursion Tree for F(5)
5
F(5)
F(4)+F(3)
2
3
F(4) F(3)
F(3)+F(2) F(2)+F(1)
1
1 1
2
F(3) F(2) F(2) F(1)
F(2)+F(1) F(1)+F(0) F(1)+F(0)
1 1 1 0 1 0
F(2) F(1) F(1) F(0) F(1) F(0)
F(1)+F(0)
1 0
F(1) F(0)
Euclid’s gcd Algorithm (1)
• Consider calculating the gcd(a, b)
– gcd(35, 25)  5
– gcd(48, 32)  16
– gcd(60, 54)  6
– gcd(70, 27)  1
Euclid’s gcd Algorithm (2)
• Let gcd(a, b) = d
• Then we can write: a = x*d, b = y*d for some positive integers x & y
>= 1
• Assume that a > b. Then we can write a = q*b + r, where
– “q” is some positive integer >= 1
– “r” is the remainder of a divided by b, i.e., r = a % b

• a = q*b + r
• r = a – q*b
• r = x*d – q*y*d = (x-q*y)*d

• This means that “d” is also the gcd for “r”


• So, to compute gcd(a, b)  compute gcd(b, r) (Recursive formulation)
• We stop when r = 0. That is, gcd(a, 0)  a (Base case)
Euclid’s gcd Algorithm (3)
[Link]

• gcd(35, 25)  gcd(25, 10)  gcd(10, 5)  gcd(5, 0)  5

• gcd(48, 32)  gcd(32, 16)  gcd(16, 0)  16

• gcd(60, 54)  gcd(54, 6)  gcd(6, 0)  6

• gcd(70, 27)  gcd(27, 16)  gcd(16, 11)  gcd(11, 5)  gcd(5, 1) 


gcd(1, 0)  1

You might also like