CS 310 – Advanced Data Structures and Algorithms Recursion June 27, 2017 Tong Wang UMass Boston CS 310 June 27, 2017 1 / 20
Recursion Recursion means defining something, such as a function, in terms of itself Recursion is a powerful problem-solving technique that often produces very clean solutions. Recursive solutions can be easier to understand and to describe than iterative solutions. Basic rules: Base case: Always have at least one case that can be solved without recursion Make progress: Any recursive call must progress toward a base case Always assume that the recursive call works Never duplicate work by solving the same instance of a problem in separate recursive calls Tong Wang UMass Boston CS 310 June 27, 2017 2 / 20
Background: Proof by Mathematic Induction Establish the basis the basis is the easy case that can be shown by hand. Assume the hypothesis assumes that the theorem is true for some arbitrary case and that, under this assumption, it is true for the next case. Demonstrate the induction i =1 i = n ( n +1) Example: � n 2 base case: it is obvious true when N = 1. inductive hypothesis: assume it is true for N = k. when N = k + 1, � k +1 i =1 i = ( k + 1) + k ( k +1) = ( k +1)( k +2) 2 2 Proofs by induction show us that: if we know that a statement is true for a smallest case and can show that one case implies the next case, then we know the statement is true for all cases. Tong Wang UMass Boston CS 310 June 27, 2017 3 / 20
Simple Example S(N) be the sum of the first N integers S(1) = 1, S(N) = S(N - 1) + N The above is identical to the closed form S(N) = N(N + 1) / 2 Textbook Figure 7.1 Tong Wang UMass Boston CS 310 June 27, 2017 4 / 20
How it works Use an internal stack of activation records for recursion. an activation record contains relevant information about the method, including, for instance, the values of the parameters and local variables. The stack of activation records is used because methods return in reverse order of their invocation. Textbook Figure 7.5 Tong Wang UMass Boston CS 310 June 27, 2017 5 / 20
Why it works A recursive solution solves a problem by solving a smaller instance of the same problem. When designing a recursive algorithm, we can always assume that the recursive calls work. Because when a proof is performed, this assumption is used as the inductive hypothesis. Recursive algorithms can be proven correct with mathematical induction. Tong Wang UMass Boston CS 310 June 27, 2017 6 / 20
Simple Example factorial(n) iterative (function does not call itself) if n = 0, factorial(n) = 1 if n > 0, factorial(n) = n*(n-1)*(n-2)...1 recursive (function call itself) if n = 0, factorial(n) = 1 if n > 0, factorial(n) = n*factorial(n-1) Tong Wang UMass Boston CS 310 June 27, 2017 7 / 20
Iteration vs Recursion /* iterative */ int factorial(int n) { int i = 1; /* recursive */ int res = 1; int factorial(int n) { while(i <= n) { if(n == 0) res *= i; return 1; i += 1; else } return n*factorial(n-1); return res; } } simple, eliminate the loop straightforward, loop recursive solution is through n computed from big to small iterative solution is in general computed from small to big in general Tong Wang UMass Boston CS 310 June 27, 2017 8 / 20
Iteration vs Recursion Depends what you are trying to do Recursion makes a program more elegant and readable (tree traversal) But it needs extra stack space for activation records Too much recursion can be dangerous Recursion is truly valuable when a program has no simple iterative solution Tong Wang UMass Boston CS 310 June 27, 2017 9 / 20
Fibonacci Numbers Fibonacci numbers: 0 , 1 , 1 , 2 , 3 , 5 , 8 , . . . F (0) = 0 F (1) = 1 (It has two base cases) F ( n ) = F ( n − 1) + F ( n − 2), for n ≥ 2 Closed form of Fibonacci numbers √ α = 1 + 5 2 √ β = 1 − 5 2 F n = α n − β n √ 5 Tong Wang UMass Boston CS 310 June 27, 2017 10 / 20
Too Much Recursion Let C ( n ) be the number of calls // Compute the n-th Fibonacci number // Bad algorithm to fib() made during the public static void fib( int n ) { evaluation of fib(n) if (n == 0) return 0; C (0) = C (1) = 1 if (n == 1) return 1; C ( n ) = C ( n − 1) + C ( n − 2) + 1 else C ( n ) = F ( n + 2) + F ( n − 1) − 1 return fib( n-1 ) + fib( n-2 ); } Prove by induction Tong Wang UMass Boston CS 310 June 27, 2017 11 / 20
Textbook Figure 7.7 Tong Wang UMass Boston CS 310 June 27, 2017 12 / 20
Example int s1, s2; int fib(n) { if(n == 0) return 0; else if(n == 1) return 1; else { s1 = fib(n - 1); s2 = fib(n - 2); return s1 + s2; } } Consider the above program fib(2) = 1 fib(3) = 2 fib(4) = 2 ?? Tong Wang UMass Boston CS 310 June 27, 2017 13 / 20
Example This is a mistake, even though the function looks fine Its correctness crucially depends on having local variables for storing all the intermediate results If we move the declaration s1 and s2 inside the function, it will work perfectly This kind of bug is hard to find Tong Wang UMass Boston CS 310 June 27, 2017 14 / 20
Tail Recursion Recursive methods are either tail recursive or non-tail recursive Tail recursive method has the recursive call as the last operation in the method It is more efficient because we do not need the call stack It is easy to convert tail recursive to iterative Tong Wang UMass Boston CS 310 June 27, 2017 15 / 20
Non-tail Recursion vs Tail Recursion /* tail recursion */ int factorial(int n) { /* non-tail recursion */ return helper(n, 1); int factorial(int n) { } if(n == 0) return 1; int helper(int n, int res) { else if (n > 0) { return n*factorial(n-1); return helper(n - 1, n * res); } } return res; } Tong Wang UMass Boston CS 310 June 27, 2017 16 / 20
Numerical Applications Modular arithmetic Modular exponentiation GCD Tong Wang UMass Boston CS 310 June 27, 2017 17 / 20
Modular Arithmetic Theorems If A ≡ B ( mod N ), then for any C , A + C ≡ B + C ( mod N ) 1 If A ≡ B ( mod N ), then for any D , AD ≡ BD ( mod N ) 2 If A ≡ B ( mod N ), then for any positive P , A P ≡ B P ( mod N ) 3 What is the last digit in 3333 5555 ? There are more than 15,000 digits, too prohibitive to compute directly Wanted: 3333 5555 ( mod 10) 3333 ≡ 3 ( mod 10), thus we only need 3 5555 ( mod 10) 3 4 = 81, 3 4 ≡ 1 ( mod 10) (3 4 ) 1388 = 3 5552 ≡ 1 ( mod 10) 3 5555 ≡ 27 ≡ 7 ( mod 10) Tong Wang UMass Boston CS 310 June 27, 2017 18 / 20
Modular Exponentiation How to compute x n ( mod p ) // Return x^n (mod p) when n is huge? // Assumes x, n >= 0, p>0, x<p, 0^0 = 1 // Overflow may occur if p > 31 bits Take ( mod p ) for intermediate // results – keep the numbers small public static long power( long x, long n, long p ) If n is even, x n = ( x · x ) ⌊ n 2 ⌋ { if (n == 0) If n is odd, x n = x · ( x · x ) ⌊ n 2 ⌋ return 1; long tmp = power( (x*x)%p, n/2, p ); Let M ( n ) be the number of if (n % 2 != 0) multiplications used by power tmp = (tmp*x) % p; return tmp; M ( n ) ≤ M ( ⌊ n / 2 ⌋ ) + 2 } log( n ) algorithm Tong Wang UMass Boston CS 310 June 27, 2017 19 / 20
GCD, Euclid’s Algorithm // Return the greatest common divisor public static long gcd( long a, long b ) gcd( a , b ) ≡ gcd( a − b , b ) { gcd( a , b ) ≡ gcd( b , a mod b ) if (b == 0) return a; Assume n > m , else return gcd( b, a % b); gcd( n , m ) = O (log n ) } Tong Wang UMass Boston CS 310 June 27, 2017 20 / 20
Recommend
More recommend