Recursion - Computer Algorithms

Preview:

Citation preview

Recursion

Alaa K. Al-Makhzoomy – Faculty of IT - WISE

1. Motivation

2

Suppose you want to find all the files under a directory that contains a particular word. How do you solve this problem?

There are several ways to solve this problem.

An intuitive solution is to

use recursion by searching

the files in the subdirectories

recursively.

3. Motivation – Solving Complex Problems

4

The Eight Queens puzzle consists on placing eight queens on a chessboard

such that no two queens are on the same row, same column, or same

diagonal, as shown in figure below.

Your turn: Try placing n Queens on an n*n board

Typical Example - Computing Factorial

5

Notation

n ! = n * (n-1)!

factorial( n ) = n * factorial( n-1 );

Example: Compute the value of 4!

factorial(4) = 4 * factorial( 3 )

= 4 * ( 3 * factorial(2) )

= 4 * ( 3 * (2 * factorial(1)) )

= 4 * ( 3 * ( 2 * (1 * factorial(0))))

= 4 * (3 * ( 2 * ( 1 * 1 )))

= 4 * (3 * ( 2 * 1))

= 4 * (3 * 2 )

= 4 * 6

= 24

Trace Recursive factorial

6

Main method

3

Space Required

for factorial(3)

Space Required

for factorial(2)

Space Required

for factorial(4)

4

Space Required

for factorial(3)

Space Required

for factorial(2)

Space Required

for factorial(1)

5 Stack

return 1

factorial(4)

return 4 * factorial(3)

return 3 * factorial(2)

return 2 * factorial(1)

return 1 * factorial(0)

Step 9: return 24 Step 0: executes factorial(4)

Step 1: executes factorial(3)

Step 2: executes factorial(2)

Step 3: executes factorial(1)

Step 5: return 1

Step 6: return 1

Step 7: return 2

Step 8: return 6

Step 4: executes factorial(0)

Recursive descend

Backtrack

Computing Factorial

private static int fact(int n) {

if ( n == 0 )

return 1;

else

return n*fact(n-1);

}

factorial(4) Stack Trace

8

Other Example – Recursive Summation

9

f(0) = 0;

f(n) = n + f(n-1);

Example:

f (12) = 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12

Observe that f(12) = 12 + f(11), and

f (11) = 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11

Which in turn can be computed as f(11) = 11 + f(10)

Likewise, f(10) = 10 + f(9), and so on, until f(0) = 0 is discovered

f(11)

f(10)

Recursive sum of first n numbers

1

00

nn

ini

Fibonacci Numbers

10

Fibonacci series: 0 1 1 2 3 5 8 13 21 34 55 89…

indices: 0 1 2 3 4 5 6 7 8 9 10 11

fib(0) = 0;

fib(1) = 1;

fib(index) = fib(index -1) + fib(index -2); index >=2

fib(3) = fib(2) + fib(1)

= (fib(1) + fib(0)) + fib(1)

= (1 + 0) +fib(1)

= 1 + fib(1)

= 1 + 1 = 2

Fibonacci Numbers

11

private static int fib(int n) {

if ((n == 1) || (n == 0))

return n;

else

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

}

Fibonnaci Numbers, cont.

12

Fibonnaci Numbers.

13

Fibonacci Numbers

1 (Jan) C1 1 (Feb) C1 2 (Mar) C1 C1,1 3 (Apr) C1 C1,2 C1,1

5 (May) C1 C1,3 C1,2 C1,1 C1,1,1 8 (Jun) C1 C1,4 C1,3 C1,2 C1,2,1 C1,1 C1,1,2 C1,1,1 13 (Jul) 21 (Aug) 34 (Sep) 55 (Oct) 89 (Nov) 144 (Dec)

C x,y

Represents a couple of male & female rabbits.

C1,2 is the second offspring pair descending

from couple 1.

Fibonacci sequence first appears in the book Liber Abaci (1202) by Leonardo of Pisa, known as Fibonacci.

Fibonacci considers the growth of an idealized rabbit population, assuming that: a newly born pair of rabbits, one male, one female, are put in a field; rabbits are able to mate at the age of one month so that at the end of its second month a female can produce another pair of rabbits; rabbits never die and a mating pair always produces one new pair (one male, one female) every month from the second month on. The puzzle that Fibonacci posed was: how many pairs will there be in one year? Taken from: http://en.wikipedia.org/wiki/Fibonacci_number

Fibonnaci

Numbers.

14 Images from: mathacademy.com,

Fibonacci Spiral

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …

Known as “The fingerprint of God”

See an interesting video at (watch at your own risk!) http://www.youtube.com/watch?v=e9MwNm0gXd8

Characteristics of Recursion

15

All recursive methods have the following characteristics:

One or more base cases (the simplest case) are used to stop recursion

(boundary conditions). Every recursive call reduces the original problem, bringing it

increasingly closer to a base case until it becomes that case.

In general, to solve a problem using recursion,

1. you break it into subproblems. 2. If a subproblem resembles the original problem, you can apply the same approach to

solve the subproblem recursively. 3. This subproblem is almost the same as the original problem in nature with a smaller

size.

Problem Solving Using Recursion

16

Let us consider a simple problem of printing a message for n times.

You can break the problem into two subproblems:

1. One is to print the message one time and the other is to print the message for n-1 times.

2. The second problem is the same as the original problem with a smaller size.

3. The base case for the problem is n==0.

private static void printMsg(String msg, int times) {

// printing a message a number of times if (times==0) return; System.out.println(times + " " + msg); printMsg(msg, times-1);

}

private static boolean isPalindrome ( String str ) { if (str.length() == 0 || str.length() == 1) return true; char first = str.charAt(0); char last = str.charAt(str.length() - 1); if (first != last) return false; else { str = str.substring(1, str.length() - 1); return isPalindrome( str ); } }

Version1: Palindrome

17

Examples: 100a001, MADAMIMADAM, abccba are palindromes.

Version2: Recursive Helper Methods

18

Examples: 100a001, MADAMIMADAM, abccba are palindromes.

public static boolean isPalindrome(String s) {

return isPalindrome(s, 0, s.length() - 1);

}

public static boolean isPalindrome(String s, int low, int high) {

if (high <= low) // Base case

return true;

else if (s.charAt(low) != s.charAt(high)) // Base case

return false;

else

return isPalindrome(s, low + 1, high - 1);

}

Directory Size

19

This section presents a problem that is difficult to solve without using recursion.

The problem is to find the size of a directory. The size of a directory is the sum of the sizes of all files in the directory. A directory may contain subdirectories.

directory

...

1f

1

2f

1

mf

1

1d

1

2d

1

nd

1

...

)(...)()()(...)()()( 2121 nm dsizedsizedsizefsizefsizefsizedsize

Directory Size

20

public class DirectorySize {

public static void main(String[] args) {

System.out.print("Enter a file or a directory: ");

java.util.Scanner input = new java.util.Scanner(System.in);

String s = input.nextLine();

try {

System.out.println( directorySize( new File(s) ) );

}

catch (IOException ex) {

System.out.println(ex.toString());

}

}

public static long directorySize(File file) throws java.io.FileNotFoundException{

if (!file.exists())

throw new java.io.FileNotFoundException(file + " not found");

if (file.isFile()) {

return file.length();

}

else {

File[] files = file.listFiles();

long size = 0;

for (int i = 0; i < files.length; i++)

size += directorySize(files[i]);

return size;

}

}

}

Towers of Hanoi

21

There are n disks labeled 1, 2, 3, . . ., n, and three towers labeled

A, B, and C.

No disk can be on top of a smaller disk at any time.

All the disks are initially placed on tower A.

Only one disk can be moved at a time, and it must be the top disk

on the tower.

Invented by french

mathematician

Edouard Lucas (1842)

Image from Wikipedia 7/8/2011

Towers of Hanoi, cont.

22

A B

Original position

C A B

Step 4: Move disk 3 from A to B

C

A B

Step 5: Move disk 1 from C to A

C A B

Step 1: Move disk 1 from A to B

C

A C B

Step 2: Move disk 2 from A to C

A B

Step 3: Move disk 1 from B to C

C A B

Step 7: Mve disk 1 from A to B

C

A B

Step 6: Move disk 2 from C to B

C

Solution to Towers of Hanoi

23

The Towers of Hanoi problem can be decomposed into three subproblems.

A B

Original position

C

.

.

.

A B

Step 1: Move the first n-1 disks from A to C recursively

C

.

.

.

A B

Step2: Move disk n from A to C

C

.

.

.

A B

Step3: Move n-1 disks from C to B recursively

C

.

.

.

n-1 disks

n-1 disks

n-1 disks

n-1 disks

Step 2. Move disk n from A to B

Solution to Towers of Hanoi

24

1. Move the first n - 1 disks from A to C with the assistance of tower B.

2. Move disk n from A to B.

3. Move n - 1 disks from C to B with the assistance of tower A.

Solution to Towers of Hanoi

25

public static void main(String[] args) { int n = 4; // moving disks from A to B using C as auxiliary tower System.out.println("Towers of Hanoi. The moves are:"); moveDisks(n, 'A', 'B', 'C'); } private static void moveDisks( int n, char fromTower, char toTower, char auxTower) { if (n == 1) System.out.println("Move disk " + n + " from " + fromTower + " to " + toTower); else { moveDisks(n-1, fromTower, auxTower, toTower); System.out.println("Move disk " + n + " from " + fromTower + " to " + toTower); moveDisks(n-1, auxTower, toTower, fromTower); }

Greatest Common Divisor - GCD

26

gcd(2, 3) = 1

gcd(2, 10) = 2

gcd(25, 35) = 5

gcd(14, 28) = 14

Approach 1: Brute-force, start from min(n, m) down to 1, to check if a number is common divisor for both m and n, if so, it is the greatest common divisor.

Approach 2: Euclid’s algorithm

Approach 3: Recursive method

GCD

is the largest positive integer that divides

The numbers without a remainder

Approach 2: Euclid’s algorithm

27

// Get absolute value of m and n;

t1 = Math.abs(m);

t2 = Math.abs(n);

// r is the remainder of t1 divided by t2;

r = t1 % t2;

while (r != 0) {

t1 = t2;

t2 = r;

r = t1 % t2;

}

// When r is 0, t2 is the greatest common

// divisor between t1 and t2

return t2;

Approach 3: Recursive Method

28

gcd(m, n) = n if ( m % n = 0 );

gcd(m, n) = gcd(n, m % n); otherwise;

private static int gcd(int m, int n) { if (m % n == 0) return n; else return gcd(n, m % n); }

29

Knapsack Problem

Load a knapsack with any number of items without exceeding its capacity.

//knapsack problem. Simple case - no optimization

ArrayList<Integer> items = new ArrayList<Integer> (

Arrays.asList(8, 2, 9, 4, 1, 5, 3, 4, 2, 6, 7));

ArrayList<Integer> solution = new ArrayList<Integer>();

knapsack(16, solution, items);

for (int n : solution){

System.out.println("Knapsack: " + n );

}

Picture taken from: http://en.wikipedia.org/wiki/Knapsack_problem

30

Knapsack Problem

Load a knapsack with any number of items without exceeding its capacity. private static void knapsack(int maxWeight, ArrayList<Integer> solution, ArrayList<Integer> items) { if ((maxWeight >= 0 ) && (items.size()>0) ) { int item = items.remove(0); solution.add(0, item); knapsack(maxWeight-item, solution, items); } else { int item = solution.remove(0); if (items.size()==0) return; else{ knapsack(maxWeight+item, solution, items); } } }

Picture taken from: http://en.wikipedia.org/wiki/Knapsack_problem

Fractals?

31

A fractal is a geometrical figure

just like triangles, circles, and

rectangles, but fractals can be

divided into parts, each of which is

a reduced-size copy of the whole.

Sierpiński Triangle

32

1. It begins with an equilateral triangle, which is considered to be the Sierpinski fractal of order (or level) 0, as shown in Figure (a).

2. Connect the midpoints of the sides of the triangle of order 0 to create a Sierpinski triangle of order 1, as shown in Figure (b).

3. Leave the center triangle intact. Connect the midpoints of the sides of the three other triangles to create a Sierpinski of order 2, as shown in Figure (c).

4. You can repeat the same process recursively to create a Sierpinski triangle of order 3, 4, ..., and so on, as shown in Figure (d).

Sierpinski Triangle Solution

33

p1

p3 p2

midBetweenP1P2 midBetweenP3P1

midBetweenP2P3

Sierpinski Triangle Solution

34

public void drawTriangle (int order, Point p1, ponit p2, Point p3) if (order == 0) return; else { // calculate midpoints of triangle p1-p2-p3 p12 = midPoint (p1, p2); p13 = midPoint(p1, p3); p23 = midPoint(p2, p3); // draw inner Sierpinski triangles of smaller order drawTriangle(order-1, p1, p12, p13); drawTriangle(order-1, p12, p2, p23); drawTriangle(order-1, p13, p23, p3); } }

Eight Queens

35

0

4

7

5

2

6

1

3

queens[0]

queens[1]

queens[2]

queens[3]

queens[4]

queens[5]

queens[6]

queens[7]

Eight Queens

36

0 1 2 3 4 5 6 7

0

1

2

3

4

5

6

7

upright diagonal

upleft

check

colum

n

Eight Queens

37

// start by calling: search(0); // search for a solution starting on specified row private static boolean search(int row){ if (row == SIZE) return true; for (int column=0; column < SIZE; column++){ queens[row] = column; //place a queen at row,column if (isValid(row, column) && search(row+1)){ System.out.println("Queen at: " + row + " : " + column); return true; } } return false; }//search // check if a queen can be placed at row i and column j private static boolean isValid(int row, int column){ for(int i=1; i<= row; i++){ if ( queens[row-i] == column //check column || queens[row-i] == column - i //check upleft diagonal || queens[row-i] == column + i )//check upright diagonal return false; } return true; }//isValid

Recommended