Recursion Chapter 12 Outline What is recursion n

  • Slides: 46
Download presentation
Recursion Chapter 12

Recursion Chapter 12

Outline What is recursion n Recursive algorithms with simple variables n Recursion and arrays

Outline What is recursion n Recursive algorithms with simple variables n Recursion and arrays n Recursion and complexity n s proof by induction

What is Recursion is a kind of “Divide & Conquer” n Divide & Conquer

What is Recursion is a kind of “Divide & Conquer” n Divide & Conquer n s Divide problem into smaller problems s Solve the smaller problems n Recursion s Divide problem into smaller versions of itself s Smallest version(s) can be solved directly

Coding Recursively n Remember the two imperatives: s SMALLER! » when you call the

Coding Recursively n Remember the two imperatives: s SMALLER! » when you call the method inside itself, one of the arguments has to be smaller than it was s STOP! » if the argument that gets smaller is very small (usually 0 or 1), then don’t do the recursion

Recursive Countdown n Print the numbers from N down to 1 s recursive method

Recursive Countdown n Print the numbers from N down to 1 s recursive method (stop when N is zero) public static void count. Down. From(int n) { if (n > 0) { // STOP if n == 0! System. out. print(n + " "); count. Down. From(n - 1); // SMALLER! } } to count down from 10: print 10; count down from 9 …. 10 9 8 7 6 5 4 3 2 1

Recursive Countdown n Print the numbers from N down to 1 s recursive method

Recursive Countdown n Print the numbers from N down to 1 s recursive method (stop when N is zero) public static void count. Down. From(int n) { if (n > 0) { // STOP if n == 0! System. out. print(n + " "); count. Down. From(n - 1); // SMALLER! } } to count down from 9: print 9; count down from 8…. 10 9 8 7 6 5 4 3 2 1

Recursive Countdown n Print the numbers from N down to 1 s recursive method

Recursive Countdown n Print the numbers from N down to 1 s recursive method (stop when N is zero) public static void count. Down. From(int n) { if (n > 0) { // STOP if n == 0! System. out. print(n + " "); count. Down. From(n - 1); // SMALLER! } } to count down from 0: (do nothing) 10 9 8 7 6 5 4 3 2 1

Recursive Functions n Function defined in terms of itself s one or more STOPs

Recursive Functions n Function defined in terms of itself s one or more STOPs (“base case(s)”) s one or more SMALLERs (“recursive case(s)”) n! = Fib(n) = 1 n*(n-1)! if n == 0 otherwise 0 1 Fib(n– 1)+Fib(n– 2) if n == 0 if n == 1 otherwise

The Factorial Method n Product of numbers from N down to 1 s recursive

The Factorial Method n Product of numbers from N down to 1 s recursive method public static int factorial(int n) { if (n > 0) { return n * factorial(n - 1); // smaller } else { return 1; // stop } }

Getting Smaller 4! = 4 * 3! n 3! = 3 * 2! n

Getting Smaller 4! = 4 * 3! n 3! = 3 * 2! n 2! = 2 * 1! n 1! = 1 * 0! n 0! = 1 n n! = Recursive Case Base Case 1 n*(n-1)! if n == 0 otherwise 4 * 6 = 24 3*2=6 2*1=2 1*1=1 Base Case Recursive Case

Calling a Recursive Function n Just like calling any other function System. out. println(factorial(5));

Calling a Recursive Function n Just like calling any other function System. out. println(factorial(5)); n The function returns the factorial of what you give it s because that’s what it does s it returns the factorial every time you call it s including when you call it inside its definition

Towers of Hanoi // ----- s == start, f == finish, x == extra

Towers of Hanoi // ----- s == start, f == finish, x == extra ----- // public static void hanoi(int n, char s, char f, char x) { if (n > 0) { // stop if n == 0 hanoi(n - 1, s, x, f); // smaller from start to extra System. out. println("Move a disk from " + s + " to " + f + ". "); hanoi(n - 1, x, f, s); // smaller from extra to finish } }

Recursion with Arrays n Simple recursion s s s n Values get smaller Hanoi(64)

Recursion with Arrays n Simple recursion s s s n Values get smaller Hanoi(64) calls Hanoi(63) calls Hanoi(62) Recursion with arrays s s Array length gets smaller Look at less of the array

Example Array Recursion n To Print an Array in reverse s Base Case (Stop)

Example Array Recursion n To Print an Array in reverse s Base Case (Stop) » If the array has length zero, do nothing s Recursive Case (Smaller) » » First print the last element of the array Then print the rest of the array in reverse 6 100 3 -2 8 5 18 8 -2 3 100 6 18 5

Print Array in Reverse n Give “length” of array to print, too s reduce

Print Array in Reverse n Give “length” of array to print, too s reduce “length” by 1 until get to 0 » NOTE: we’re just pretending it’s smaller public static void print. In. Reverse(int[] arr, int len) { if (len > 0) { // stop if len == 0 System. out. print(arr[len - 1] + " "); print. In. Reverse(arr, len - 1); // “smaller” array } }

Another Example n To Find the Maximum Value in an Array s Base Case

Another Example n To Find the Maximum Value in an Array s Base Case » if length is 1, the only element is the maximum s Recursive Case » » » Get the maximum from the rest of the array. . . & compare it to the last element Return the bigger 6 100 3 -2 8 18 100 5 5

Exercise n Translate the (recursive) algorithm from the previous slide into Java s Base

Exercise n Translate the (recursive) algorithm from the previous slide into Java s Base Case » if length is 1, the only element is the maximum s Recursive Case » » » Get the maximum from the rest of the array. . . & compare it to the last element Return the bigger Remember to use a “pretend” length

Working From Both Ends Sometimes we want to be able to shorten the array

Working From Both Ends Sometimes we want to be able to shorten the array at either end n Pass start and end points instead of length n Done when n s s n lo > hi (for len==0), or lo == hi (for len==1) “Sub-Array processing”

Working From Both Ends n Alternate way to find array maximum s compare first

Working From Both Ends n Alternate way to find array maximum s compare first and last elements s drop the smaller out of range we’re using s stop when array has only one element left » maximum is that one element 6 100 3 -2 8 18 5

Working From Both Ends n Alternate way to find array maximum public static int

Working From Both Ends n Alternate way to find array maximum public static int maximum(int[] arr, int lo, int hi) { if (lo == hi) { return arr[lo]; // stop! } else if (arr[lo] > arr[hi]) { return maximum(arr, lo, hi - 1); // smaller } else { return maximum(arr, lo + 1, hi); // smaller } }

Array Splitting Sub-array processing can get rid of more than one element at a

Array Splitting Sub-array processing can get rid of more than one element at a time n Binary split is a common method n s do top “half” and bottom “half” separately s combine to get answer 6 100 3 -2 100 8 18 18 100 5

Array Splitting n Alternate way to find array maximum public static int maximum(int[] arr,

Array Splitting n Alternate way to find array maximum public static int maximum(int[] arr, int lo, int hi) { if (lo == hi) { return arr[lo]; // stop! } else { int mid = lo + (hi - lo) / 2; int max. Lo = maximum(arr, lo, mid); // smaller! int max. Hi = maximum(arr, mid+1, hi); // smaller! return Math. max(max. Lo , max. Hi); } }

Defensive Programming n Consider finding the midpoint mid = lo + (hi – lo)

Defensive Programming n Consider finding the midpoint mid = lo + (hi – lo) / 2; s could just do (hi + lo) / 2 n BUT what if the array is HUGE s hi == 2, 000, 000; lo == 1, 000, 000 s (hi + lo) / 2 == -647, 483, 648 (int overflow) s lo + (hi – lo) / 2 == 1, 500, 000 (no overflow) » hi and lo both positive, so no underflow worry

Array Recursion Exercise n Given an array and a number, find out if the

Array Recursion Exercise n Given an array and a number, find out if the number is in the array (contains method) » NOTE: the array is unsorted s Base Case(s) » ? s Recursive Case(s) » ?

Recursive Algorithm Analysis n Still in terms of size of problem s size of

Recursive Algorithm Analysis n Still in terms of size of problem s size of n for factorial(n), fibonacci(n), … s size of array/linked structure in print. In. Reverse, find. Maximum, … Base case probably just one operation n Recursive case recursive count n s amount of work for n in terms of amount of work for n - 1

Work for print. In. Reverse (Array) n N is the “length” of the array

Work for print. In. Reverse (Array) n N is the “length” of the array (len) public static void print. In. Reverse(int[] arr, int len) { if (len > 0) { // stop if len == 0 System. out. print(arr[len - 1] + " "); print. In. Reverse(arr, len - 1); // “smaller” array } } s if len == 0: compare len to 0: W(0) = 1 s if len > 0: compare len to 0, print arr[len-1], call print. In. Reverse with len-1: » W(len) = 2 + W(len - 1)

Recurrence Relation n When W(n) defined in terms of W(n – 1)… s or

Recurrence Relation n When W(n) defined in terms of W(n – 1)… s or some other smaller value than n … it’s called a recurrence relation n It’s a recursive definition of W n s has a base case (n = 0 or n = 1 or …) s has a recursive case public static int W(int n) { if (n == 0) return 1; else return 2 + W(n – 1); }

Solving by Inspection n Work for print. In. Reverse: s W(0) = 1 s

Solving by Inspection n Work for print. In. Reverse: s W(0) = 1 s W(1) = 2 + W(0) = 3 s W(2) = 2 + W(1) = 5 s W(3) = 2 + W(2) = 7 s W(4) = 2 + W(3) = 9 s… s W(N) = 2 + W(N– 1) (change) +2 +2 linear: factor of 2 = 2 N + 1?

Solving by Inspection n Table with N and Work for N (W) s calculate

Solving by Inspection n Table with N and Work for N (W) s calculate change in work (ΔW) for each step N W recurrence ΔW 0 1 1 3 W(0) + 2 2 2 5 W(1) + 2 2 3 7 W(2) + 2 2 4 9 W(3) + 2 2 5 11 W(4) + 2 2 N ?

Solving by Inspection: Linear n Change in W will be a constant > 0

Solving by Inspection: Linear n Change in W will be a constant > 0 s probably: W(N) = (ΔW)N + W(0) N W recurrence ΔW 0 1 1 3 W(0) + 2 2 2 5 W(1) + 2 2 3 7 W(2) + 2 2 4 9 W(3) + 2 2 5 11 W(4) + 2 2 N 2 N + 1

Solving by Inspection: Quadratic n Add column for change in ΔW s Δ(ΔW) constant

Solving by Inspection: Quadratic n Add column for change in ΔW s Δ(ΔW) constant W(N) = (Δ(ΔW)/2)N 2 + … N 2 N W recurrence ΔW 0 0 1 1 1 3 W(0) + 2 2 4 2 7 W(1) + 4 9 3 13 16 4 25 5 N recurrence(2) Δ(ΔW) 4 ΔW(1) + 2 2 W(2) + 6 6 ΔW(2) + 2 2 21 W(3) + 8 8 ΔW(3) + 2 2 31 W(4) + 10 10 ΔW(4) + 2 2 N 2 + ? N++? 1 W(N-1) + 2 N 2 N

Proving Your Formula n You only looked at a few values s will the

Proving Your Formula n You only looked at a few values s will the formula you got work on all values? n Can prove that a formula will work s proof by induction n Assume it works up to an arbitrary N – 1 s use recurrence relation to show it works for N s proves it works up to any N

Proof by Induction (Linear) Suppose W(n) = 2 n + 1 for n <

Proof by Induction (Linear) Suppose W(n) = 2 n + 1 for n < N n What is W(N)? n s W(N) = W(N – 1) + 2 s but N – 1 < N, so: (recurrence relation) » W(N – 1) = 2(N – 1) + 1 = 2 N – 2 +1 = 2 N – 1 s W(N) = (2 N – 1) + 2 = 2 N + 1 s so W(N) also = 2 N + 1 s and that’s for any N > 0

Proof by Induction (Quadratic) Suppose W(n) = n 2 + n + 1 for

Proof by Induction (Quadratic) Suppose W(n) = n 2 + n + 1 for n < N n What is W(N)? n s W(N) = W(N – 1) + 2 N s but N – 1 < N, so: (recurrence relation) » W(N – 1) = (N – 1)2 + (N – 1) + 1 = N 2 – N + 1 s W(N) = (N 2 – N + 1) + 2 N = N 2 + N + 1 s so W(N) also = N 2 + N + 1 s and that’s for any N > 0

Exercise n Given recurrence reln W(N) = W(N-1) + 4, prove that W(N) =

Exercise n Given recurrence reln W(N) = W(N-1) + 4, prove that W(N) = 4 N + 5 n Given W(N) = W(N-1) + 2 N + 1, prove that W(N) = N 2 + 2 N

Analyzing Array Splitting n Split array into two equal(ish) pieces s easiest to analyze

Analyzing Array Splitting n Split array into two equal(ish) pieces s easiest to analyze if N is a power of 2 » 1, 2, 4, 8, 16, … s or one less than that (if middle item removed) » 0, 1, 3, 7, 15 s makes exactly equal splits n Need to factor in change in N

Analyzing Array Splitting n Work when splitting exactly s find maximum using array splitting

Analyzing Array Splitting n Work when splitting exactly s find maximum using array splitting 6 100 3 -2 8 18 5 W(8) W(4) s W(8) = 2 W(4) W(2) s W(2 N) = 2 W(N) W(2) 35

Array Splitting public static int maximum(int[] arr, int lo, int hi) { if (lo

Array Splitting public static int maximum(int[] arr, int lo, int hi) { if (lo == hi) { // 1 comparison return arr[lo]; // 1 array access } else { int mid = lo + (hi - lo) / 2; // 3 math ops int max. Lo = maximum(arr, lo, mid); // 1 asgn + REC int max. Hi = maximum(arr, mid+1, hi); // 1 asgn + REC return (max. Lo > max. Hi) ? max. Lo : max. Hi; // 1 comparison } } W(1) = 2 DW / DN W(2) = 7 + 2 W(1) = 7 + 2(2) = 11 + 9 / +1 9 N – 7 W(4) = 7 + 2 W(2) = 7 + 2(11) = 29 +18 / +2 9 N – 7 W(8) = 7 + 2 W(4) = 7 + 2(29) = 65 +36 / +4 9 N – 7 W(16) = 7 + 2 W(8) = 7 + 2(65) = 137 +72 / +8 9 N – 7

find. Maximum by Splitting n Split array into two (nearly equal) parts s look

find. Maximum by Splitting n Split array into two (nearly equal) parts s look at only powers of 2 » even splits all the way down s looks like W(N) = 9 N – 7 » linear » works for N <= 16 s do induction on 2 N instead of N+1 s (later we’ll do 2 N+1)

Proof by Induction (Part 1) Assume W(n) = 9 n – 7 for n

Proof by Induction (Part 1) Assume W(n) = 9 n – 7 for n < 2 N n What’s W(2 N)? n s W(2 N) = 7 + 2 W(N) s but N < 2 N, so W(N) = 9 N – 7… s … so W(2 N) = 7 + 2(9 N– 7) = 7 + 18 N – 14 = 18 N – 7 = 9(2 N) – 7 s same formula works for all even N

Proof by Induction (Part 2) Assume W(n) = 9 n – 7 for n

Proof by Induction (Part 2) Assume W(n) = 9 n – 7 for n < 2 N n What’s W(2 N + 1)? n s W(2 N + 1) = 7 + W(N) + W(N+1) s but N < N+1 < 2 N, so … s W(2 N + 1) = 7 + (9 N – 7) + (9(N+1) – 7) = 7 + 9 N – 7 + 9 N + 9 – 7 = 18 N + 9 – 7 = 9(2 N+1) – 7 s same formula works for all odd N

Towers of Hanoi N = number of disks n Work = number of moves

Towers of Hanoi N = number of disks n Work = number of moves n s W(0) = 0 s W(1) = W(0) + 1 + W(0) = 1 s W(2) = W(1) + 1 + W(1) = 3 s W(3) = W(2) + 1 + W(2) = 7 s W(4) = W(3) + 1 + W(3) = 15 s W(5) = W(4) + 1 + W(4) = 31 (change) +1 +2 +4 +8 +16

Solve by Inspection n Work doubles at each step of N s sounds exponential

Solve by Inspection n Work doubles at each step of N s sounds exponential s compare work with 2 N s 2 N = W(N) + 1 s so work = 2 N – 1 s exponential N W(N) 2 N 0 0 1 1 1 2 2 3 4 3 7 8 4 15 16 5 31 32 N 2 N – 1 2 N

Proof by Induction Assume W(n) = 2 n – 1 for n < N

Proof by Induction Assume W(n) = 2 n – 1 for n < N n What’s W(N)? n s W(N) = 1 + 2 W(N– 1) = 1 + 2(2 N– 1 – 1) = 1 + 2 N – 2 = 2 N – 1 s formula works for all N

Exercise n How much work is done by print. In. Reverse for the linked

Exercise n How much work is done by print. In. Reverse for the linked structure? private void print. In. Reverse(Node first) { if (first != null) { // stop if list is empty! print. In. Reverse(first. next); // smaller! System. out. println(first. data + " "); } } s write recurrence relation s solve order of magnitude

Next Time n Faster sorting methods

Next Time n Faster sorting methods