Presentation is loading. Please wait.

Presentation is loading. Please wait.

Unit 7 1 Unit 7: Recursion H Recursion is a fundamental programming technique that can provide an elegant solution to a certain kinds of problems H In.

Similar presentations


Presentation on theme: "Unit 7 1 Unit 7: Recursion H Recursion is a fundamental programming technique that can provide an elegant solution to a certain kinds of problems H In."— Presentation transcript:

1 unit 7 1 Unit 7: Recursion H Recursion is a fundamental programming technique that can provide an elegant solution to a certain kinds of problems H In recursion we solve a problem by reducing it to a similar problem of “smaller size” basic programming concepts object oriented programming topics in computer science syllabus

2 unit 7 2 Factorial Example: implementation 1 H Problem: find the factorial of an integer number, defined for a positive number as follows: n!=1*2*3*…*n H A simple implementation would use a loop that goes over the expression and keeps track of the partial multiplication

3 unit 7 3 Factorial Example: code 1 // Computes the factorial of a number public static long factorial(long n) { long multiplication = 1; for (int i=1; i<n; i++) { multiplication *= i; } return multiplication; }

4 unit 7 4 Factorial Example:implementation 2 H We observe that for every integer n, n>1 : n! = 1*2*...n = (1*2*...n-1)*n = (n-1)! * n H So we have: 1! = 1 n! = (n-1)!*n, for n>1 H We can use these observations to derive a new implementation for computing n!

5 unit 7 5 Computing n! H If n is 1, n!=1 H If n>1, use n!=(n-1)!*n H But do we know how to compute (n-1)! ? H Since the reduction holds for all n>1, we can reduce the problem from n! to (n-1)! to (n-2)! etc, until we reach the problem of computing 1! which is easy

6 unit 7 6 Factorial recursive computation 5! 5 * 4! 4 * 3! 3 * 2! 2 * 1! 1 2 6 24 120

7 unit 7 7 Factorial Example: code 2 // Computes the factorial of a number. public static long factorial(long n) { if (n==1) { return 1; } return n*factorial(n-1); }

8 unit 7 8 Factorial Example: proof of correctness H We can prove that our implementation of ‘factorial’ is correct using mathematical induction H We have to show the following factorial gives the correct result for n=1 If ‘factorial’ returns the correct answer for an arbitrary number n such that n>1, then ‘factorial’ returns the correct answer for n+1 H Now the proof is immediate

9 unit 7 9 Factorial Example: shorter code 2 // Computes the factorial of a number. public static long factorial(long n) { return (n==1) ? 1 : n*factorial(n-1); }

10 unit 7 10 Recursive Programming H A method in Java can invoke itself; if set up that way, it is called a recursive method H A recursive method has: a base case which solves the task without a recursive call a recursive step which solves the task by reducing it and using a recursive call H If there is no base case the sequence of reductions will not terminate; we call this an infinite recursion

11 unit 7 11 isNumeric() Example H Problem: check if a given string consists only of digits H We want to write a method isNumeric() that for a given string would return true only if all the characters in the string are in ‘0’, ‘1’,..., ‘9’ H A simple implementation would go over the characters of the string in a loop and return false if a non-digit character is found

12 unit 7 12 isNumber(): implementation 1 // Checks if a given string consists only // Of digit symbols public static boolean isNumeric(String s) { for (int i=0; i<s.length(); i++) { char c = s.charAt(i); if (c ’9’) { return false; } return true; }

13 unit 7 13 isNumeric(): recursive formulation H Base case: an empty string doesn’t contain non- digit characters, therefore return true for the empty string H If the first character of s is non-digit then return false H Recursive step: if the first character of s is a digit symbol, then s is numeric if and only if the rest of s (without the first character) is numeric

14 unit 7 14 isNumber(): implementation 2 // Checks if a given string consists only // of digit symbols. public static boolean isNumeric(String s) { if (s.length()==0) { return true; } char c = s.charAt(0); return (c>=‘0’ && c<=‘9’ && isNumeric(s.substring(1)); }

15 unit 7 15 Fibonacci Series Example H Fibonacci series is a series of integers f 0, f 1, f 2,... that is defined as follows: f 0 = 1 f 1 = 1 f n = f n-1 +f n-2 for n>1

16 unit 7 16 Fibonacci Example: implementation // Returns the n number in Fibonacci series public static int fibonacci(int n) { if (n<=0) { return 1; } return fibonacci(n-1)+fibonacci(n-2); } issue of efficienty

17 unit 7 17 Recursive Programming H Note that just because we can use recursion to solve a problem, doesn't mean we should (there is a cost associated with multiple method calls) H In fact, we usually would not use recursion to solve the previous problems (why?) H However, for some problems, recursion provides an elegant solution, often cleaner than an iterative version H We will see next a few examples where a recursive solution is very appropriate

18 unit 7 18 GCD Example H The Greatest Common Divisor of two integers a,b is defined as the largest integer that divides both a and b; we denote the greatest common divisor of a and b by gcd(a,b) Consider the problem of finding the gcd of two integers, where w.l.o.g. a>b: H Base case: if b divides a, then gcd(a,b)=b (because b also divides itself and there is no greater integer that divides b)  Recursive step: if b doesn’t divide a...

19 unit 7 19 GCD Example: Recursive Step Let m denote the remainder of the division of a by b ( m=a%b ), then: a = k*b+m, m<b gcd(a,b)=gcd(b,m) because   every integer that divides both a and b must also divide m   every integer that divides both b and m must also divide a H Recursive step: gcd(a,b)=gcd(b,a%b) H Here the recursive solution is very appropriate

20 unit 7 20 Example: the Catalan number Example: the Catalan number H The n th Catalan number - C n - counts the number of valid strings of length 2n which: consist of n '(' symbols and n ')' symbols in every prefix the number of '(' symbols are at least as big as the number of ')' symbols examples: "(()())" is valid, "())(()" is not H Base case: C 0 =1 - there is only a single string of size 0, the empty string "" H Recursive step: for n>0, Cn=  k=1..n (C k-1 *C n-k )

21 unit 7 21 Catalan Example // Return the n'th Catalan number. public static int catalan(int n) { if (n==0) { return 1; } int sum = 0; for (int k=1; k<=n; k++) { sum += catalan(k-1)*catalan(n-k); } return sum; }

22 unit 7 22 hasPartialSum() Example H Problem: given a series of integers a 1, a 2,..., a n and a number s, we want to determine whether there is a partial series whose elements sum up to s H Base case: if the series is empty, the answer is true iff s is zero H Recursive step: otherwise if the last element is not included in the partial series, reduce the problem to finding a partial sum s in the rest of the series if the last element is included, reduce the problem to finding a partial sum s- a N in the rest

23 unit 7 23 hasPartialSum(): code // Check if a given series of integers has a partial // series whose sum equals a given integer. // length indicates the taken length of the series public static boolean hasPartialSum( int[] series, int sum, int length) { if (length==0) { return sum==0; } return hasPartialSum(series, sum, length-1) || hasPartialSum(series, sum-series[length-1], length-1); }

24 unit 7 24 Towers of Hanoi Example

25 unit 7 25 Towers of Hanoi Example

26 unit 7 26 Towers of Hanoi Example

27 unit 7 27 Towers of Hanoi Example

28 unit 7 28 Towers of Hanoi Example

29 unit 7 29 Towers of Hanoi Example

30 unit 7 30 Towers of Hanoi Example

31 unit 7 31 Towers of Hanoi Example

32 unit 7 32 Towers of Hanoi Example

33 unit 7 33 Towers of Hanoi Example

34 unit 7 34 Towers of Hanoi Example

35 unit 7 35 Towers of Hanoi Example

36 unit 7 36 Towers of Hanoi Example

37 unit 7 37 Towers of Hanoi Example

38 unit 7 38 Towers of Hanoi Example

39 unit 7 39 Towers of Hanoi Example

40 unit 7 40 Towers of Hanoi: schematic code // Solves the Towers of Hanoi problem for a // given number of disks. public static void solve( Pile from, Pile to, Pile using, int n) { if (n==1) { to.addDisk(from.removeDisk()); return; } solve(from, using, to, n-1); solve(from, to, using, 1); solve(using, to, from, n-1); }

41 unit 7 41 File System Example H Suppose we want to list all the files under a given folder: Let L be the list of all files and folders directly under f For each element f1 in L :  if f1 is a folder, list folders under f1 (recursive step)  otherwise, print the name of f1 (base case)

42 unit 7 42 File System Example import java.io.File; // List all files under a given folder public static void listFiles(File folder) { String[] files = folder.list(); for (int i=0; i<files.length; i++) { File file = new File(folder, files[i]); if (file.isDirectory()) { listFiles(file); } else { System.out.println(file); }

43 unit 7 43 Indirect Recursion H A method invoking itself is considered to be direct recursion H A method could invoke another method, which invokes another, etc., until eventually the original method is invoked again H For example, method m1 could invoke m2, which invokes m3, which in turn invokes m1 again H This is called indirect recursion, and requires all the same care as direct recursion H It is often more difficult to trace and debug

44 unit 7 44 How does recursion work? H Let’s examine again the implementation of factorial public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; }  This solution may appear magical, since we never explicitly say how to compute factorial

45 unit 7 45 How does recursion work? H In the non-recursive solution the code describes the whole process of the computation: public static long factorial(int n) { long multiplication = 1; for (int i=1; i<n; i++) { multiplication *= i; } return multiplication; } H This implementation corresponds to the explicit understanding of the whole computation

46 unit 7 46 How does recursion work? H On the other hand, in order to understand a recursive method we don’t have to follow the details of the computation process: public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } H How is 5! computed? - simply, we call factorial(4) to compute 4!, and multiply the result by 5

47 unit 7 47 How does recursion work? H and how is 4! computed? when trying to understand a recursive solution, it’s best to avoid thinking this way H Instead, assuming that the method works for smaller inputs, we try to understand how it uses this assumption to solve the problem with the current input; this + mathematical induction is sufficient H We will explain next the process by which the computer executes a recursive method

48 unit 7 48 Recursion: implementation H When we execute a Java program, the virtual machine creates a thread that processes the program code H The thread begins in the first statement of the main() method of our program, and advances according to the flow of the program until it reaches the end of main() H The thread is allocated a section of memory that is called its Runtime Stack

49 unit 7 49 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( )args =

50 unit 7 50 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = n = 4

51 unit 7 51 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 4

52 unit 7 52 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 4 factorial( )

53 unit 7 53 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 3 n = 4 factorial( )

54 unit 7 54 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 3 n = 4 factorial( ) n = 2

55 unit 7 55 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 3 n = 4 factorial( ) n = 2 factorial( )n = 1

56 unit 7 56 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 3 n = 4 factorial( ) n = 2 1

57 unit 7 57 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 3 n = 4 factorial( ) 2

58 unit 7 58 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 4 factorial( ) 6

59 unit 7 59 Recursion: Runtime Stack public static long factorial(int n) { if (n==1) { return 1; } return factorial(n-1)*n; } public static void main(String[] args) { int n = EasyInput.readInt(“N:”); String input = EasyInput.readString(); System.out.println(n+”! = “+ factorial(n)); } main( ) args = input = n = 4 24


Download ppt "Unit 7 1 Unit 7: Recursion H Recursion is a fundamental programming technique that can provide an elegant solution to a certain kinds of problems H In."

Similar presentations


Ads by Google