Upload
linette-watts
View
278
Download
3
Embed Size (px)
Citation preview
RecursionRecursion
Chapter 12Chapter 12
OutlineOutline
What is recursionWhat is recursion Recursive algorithms with simple variablesRecursive algorithms with simple variables Recursion and the run-time stackRecursion and the run-time stack Recursion and arraysRecursion and arrays Recursion and linked structuresRecursion and linked structures Recursion and complexityRecursion and complexity
proof by inductionproof by induction
What is RecursionWhat is Recursion
Recursion is a kind of “Divide & Conquer”Recursion is a kind of “Divide & Conquer” Divide & ConquerDivide & Conquer
Divide problem into smaller problemsDivide problem into smaller problems Solve the smaller problemsSolve the smaller problems
RecursionRecursion Divide problem into smaller versions of Divide problem into smaller versions of itselfitself Smallest version(s) can be solved directlySmallest version(s) can be solved directly
Recursive StructuresRecursive Structures
Getting the smallest doll from a set of Getting the smallest doll from a set of Russian dolls:Russian dolls:
If this isn’t the smallest dollIf this isn’t the smallest doll open it upopen it up get the smallest doll from the set of Russian get the smallest doll from the set of Russian
dolls insidedolls inside
““Recursive” ImagesRecursive” Images
Image where smaller part is same as wholeImage where smaller part is same as whole but smaller (duh!)but smaller (duh!)
Fern has frondsFern has fronds ““fronds” are justfronds” are just
smaller fernssmaller ferns
Recursive AlgorithmsRecursive Algorithms
Recursive algorithm calls itselfRecursive algorithm calls itself open Russian dolls: open doll and open the open Russian dolls: open doll and open the
(smaller) Russian dolls inside(smaller) Russian dolls inside draw a fern: draw the stem, then draw three draw a fern: draw the stem, then draw three
(smaller) ferns at the end of the stem(smaller) ferns at the end of the stem Problem: when to stop?Problem: when to stop?
Russian dolls: this doll won’t openRussian dolls: this doll won’t open ferns: this fern is less than one pixel tallferns: this fern is less than one pixel tall
Coding RecursivelyCoding Recursively
Remember the two imperatives:Remember the two imperatives: SMALLER!SMALLER!
» when you call the method inside itself, one of the when you call the method inside itself, one of the arguments has to be smaller than it wasarguments has to be smaller than it was
STOP!STOP!» if the argument that gets smaller is very small if the argument that gets smaller is very small
(usually 0 or 1), then don’t do the recursion(usually 0 or 1), then don’t do the recursion
Recursive CountdownRecursive Countdown
Print the numbers from N down to 1Print the numbers from N down to 1 recursive method (stop when N is zero)recursive method (stop when N is zero)public static void countDownFrom(int n) {public static void countDownFrom(int n) {
if (n > 0) {if (n > 0) { // STOP if n == 0!// STOP if n == 0!
System.out.print(n + " ");System.out.print(n + " ");
countDownFrom(n - 1);countDownFrom(n - 1); // SMALLER!// SMALLER!
}}
}}
10 9 8 7 6 5 4 3 2 1 print 10; count down from 9 ….
to count down from 10:
Recursive CountdownRecursive Countdown
Print the numbers from N down to 1Print the numbers from N down to 1 recursive method (stop when N is zero)recursive method (stop when N is zero)public static void countDownFrom(int n) {public static void countDownFrom(int n) {
if (n > 0) {if (n > 0) { // STOP if n == 0!// STOP if n == 0!
System.out.print(n + " ");System.out.print(n + " ");
countDownFrom(n - 1);countDownFrom(n - 1); // SMALLER!// SMALLER!
}}
}}
10 9 8 7 6 5 4 3 2 1 print 9; count down from 8….
to count down from 9:
Recursive CountdownRecursive Countdown
Print the numbers from N down to 1Print the numbers from N down to 1 recursive method (stop when N is zero)recursive method (stop when N is zero)public static void countDownFrom(int n) {public static void countDownFrom(int n) {
if (n > 0) {if (n > 0) { // STOP if n == 0!// STOP if n == 0!
System.out.print(n + " ");System.out.print(n + " ");
countDownFrom(n - 1);countDownFrom(n - 1); // SMALLER!// SMALLER!
}}
}}
10 9 8 7 6 5 4 3 2 1 (do nothing)
to count down from 0:
Recursive Fern DrawingRecursive Fern Drawing
public void drawFern(double x, double y, double angle, double size) {public void drawFern(double x, double y, double angle, double size) {if (size > 1.0) {if (size > 1.0) { // STOP if size <= 1.0!// STOP if size <= 1.0!
double[] end;double[] end;double length = size * 0.5;double length = size * 0.5;end = drawStem(x, y, angle, length);end = drawStem(x, y, angle, length); // private method// private methoddouble smaller = size * 0.5;double smaller = size * 0.5; // SMALLER!// SMALLER!drawFern(end[0], end[1], angle+60, smaller);drawFern(end[0], end[1], angle+60, smaller);drawFern(end[0], end[1], angle, smaller);drawFern(end[0], end[1], angle, smaller);drawFern(end[0], end[1], angle-60, smaller);drawFern(end[0], end[1], angle-60, smaller);
}}}} This will draw a fern
It’s what the drawFern method does
Recursive FunctionsRecursive Functions
Function defined in terms of itselfFunction defined in terms of itself one or more STOPs (“base case(s)”)one or more STOPs (“base case(s)”) one or more SMALLERs (“recursive case(s)”)one or more SMALLERs (“recursive case(s)”)
n! =1 if n == 0n*(n-1)! otherwise
Fib(n) =1 if n == 01 if n == 1Fib(n–1)+Fib(n–2) otherwise
The Factorial MethodThe Factorial Method
Product of numbers from N down to 1Product of numbers from N down to 1 recursive methodrecursive methodpublic static int factorial(int n) {public static int factorial(int n) {
if (n > 0) {if (n > 0) {
return n * factorial(n - 1);return n * factorial(n - 1); // smaller// smaller
} else {} else {
return 1; return 1; // stop// stop
}}
}}
Getting SmallerGetting Smaller
4! = 4 * 3!4! = 4 * 3! Recursive CaseRecursive Case 4 * 6 = 244 * 6 = 24 3! = 3 * 2!3! = 3 * 2! Recursive CaseRecursive Case 3 * 2 = 63 * 2 = 6 2! = 2 * 1!2! = 2 * 1! Recursive CaseRecursive Case 2 * 1 = 22 * 1 = 2 1! = 1 * 0!1! = 1 * 0! Recursive CaseRecursive Case 1 * 1 = 11 * 1 = 1 0! = 10! = 1 Base CaseBase Case
n! =1 if n == 0n*(n-1)! otherwise
Base Case
Recursive Case
Calling a Recursive FunctionCalling a Recursive Function
Just like calling any other functionJust like calling any other functionSystem.out.println(factorial(5));System.out.println(factorial(5));
The function returns the factorial of what The function returns the factorial of what you give ityou give it because because that’s what it doesthat’s what it does it returns the factorial it returns the factorial every time you call itevery time you call it including when you call it inside its definitionincluding when you call it inside its definition
Tracing the RecursionTracing the Recursion
Each call to the function is Each call to the function is independentindependent it has its own argument(s)it has its own argument(s) it has its own local variablesit has its own local variables
But we very well might get confusedBut we very well might get confused 20 or 30 variables all named “n” lying around20 or 30 variables all named “n” lying around
The computer does notThe computer does not it uses the “run-time stack” to keep trackit uses the “run-time stack” to keep track
Tracing the RecursionTracing the Recursion
Don’t try to trace the calls normallyDon’t try to trace the calls normally it’s very confusingit’s very confusing
Stack up method callsStack up method calls main calls factorial(4)main calls factorial(4) in factorial(4):in factorial(4):
» 4 > 0, so4 > 0, so
» return 4 * factorial(3)return 4 * factorial(3)
» in factorial(3):in factorial(3):• 3 > 0, so3 > 0, so• return 3 * factorial(2)return 3 * factorial(2)
mainSystem.out.println(…)
factorial(4)return 4 * …
factorial(3)return 3 * …
factorial(2)return 2 * …
factorial(1)return 1 * …
mainSystem.out.println(24)
factorial(4)return 4 * 6
factorial(3)return 3 * 2
factorial(2)return 2 * 1
factorial(1)return 1 * 1
factorial(0)return 1
ExerciseExercise
Write a recursive function to calculate the Write a recursive function to calculate the (non-negative integer) power of an integer(non-negative integer) power of an integer Hint: it’ll look a LOT like the one for factorialHint: it’ll look a LOT like the one for factorial
nk = 1 if k == 0n*nk-1 otherwise
Towers of HanoiTowers of Hanoi
Buddhist monks in HanoiBuddhist monks in Hanoi Set the task of moving golden disks (64) Set the task of moving golden disks (64)
around diamond needles (3)around diamond needles (3) all disks different sizesall disks different sizes never put a bigger disk on a littler onenever put a bigger disk on a littler one
When all 64 disks have been moved from When all 64 disks have been moved from the starting needle to the ending, the starting needle to the ending, the the universe will enduniverse will end
(In class demo – 4 disks)
What Would be Easy?What Would be Easy?
What if there were only one disk?What if there were only one disk?
Start Peg End PegExtra Peg
More Disks?More Disks?
Start Peg (5) End Peg (5)Extra Peg (5)
Get top disks “out of the way” (takes MANY moves)
Start Peg (4) Extra Peg(4)End Peg (4)
Towers of Hanoi (5 disks)Towers of Hanoi (5 disks)
Start Peg (5) End Peg (5)Extra Peg (5)
Move bottom disk (one move)
Towers of Hanoi (5 disks)Towers of Hanoi (5 disks)
Start Peg (5) End Peg (5)Extra Peg (5)
Finish moving the top disks over to the end peg (MANY moves)
Extra Peg (4) End Peg(4)Start Peg (4)
Towers of Hanoi (5 disks)Towers of Hanoi (5 disks)
Start Peg End PegExtra Peg
All done!
Towers of Hanoi (Version 1)Towers of Hanoi (Version 1)
If there’s only one diskIf there’s only one disk move it to the end pegmove it to the end peg
ElseElse move the top disks out of the waymove the top disks out of the way
» extra peg becomes end peg for one less disksextra peg becomes end peg for one less disks
move the bottom disk to the end pegmove the bottom disk to the end peg move the top disks onto the end pegmove the top disks onto the end peg
» start peg becomes extra pegstart peg becomes extra peg
What’s Easier than One Disk?What’s Easier than One Disk?
With no disks, there’d be nothing to do!With no disks, there’d be nothing to do! with one disk:with one disk:
» move zero disks out of the waymove zero disks out of the way
» move bottom disk to end pegmove bottom disk to end peg
» mover zero disks onto bottom diskmover zero disks onto bottom disk
same as for more than one disksame as for more than one disk Stop when n = 0 instead of when n = 1Stop when n = 0 instead of when n = 1
when n = 0, do nothingwhen n = 0, do nothing
Towers of Hanoi (Simplified)Towers of Hanoi (Simplified)
// ----- s == start, f == finish, x == extra ----- //// ----- s == start, f == finish, x == extra ----- //
public static void hanoi(int n, char s, char f, char x) {public static void hanoi(int n, char s, char f, char x) {
if (n > 0) {if (n > 0) { // // stopstop if n == 0 if n == 0
hanoi(n - 1, s, x, f);hanoi(n - 1, s, x, f); // // smallersmaller from start to extra from start to extra
System.out.println("Move a disk from " System.out.println("Move a disk from " + s + " to " + f + ".");+ s + " to " + f + ".");
hanoi(n - 1, x, f, s);hanoi(n - 1, x, f, s); // // smallersmaller from extra to finish from extra to finish
}}
}}
Recursion with ArraysRecursion with Arrays
Simple recursionSimple recursion Values get smallerValues get smaller Hanoi(64) calls Hanoi(63)Hanoi(64) calls Hanoi(63) Hanoi(63) calls Hanoi(62)Hanoi(63) calls Hanoi(62)
Recursion with arraysRecursion with arrays Array length gets smallerArray length gets smaller Look at less of the arrayLook at less of the array
Example Array RecursionExample Array Recursion
To Print an Array in reverseTo Print an Array in reverse Base Case (Stop)Base Case (Stop)
» If the array has length zero, do nothingIf the array has length zero, do nothing
Recursive Case (Smaller)Recursive Case (Smaller)» First print the last element of the arrayFirst print the last element of the array» Then print the rest of the array in reverseThen print the rest of the array in reverse
6 100 3 -2 8 18 5
5 5 18 8 -2 3 100 6
Print Array in ReversePrint Array in Reverse
Give “length” of array to print, tooGive “length” of array to print, too reduce “length” by 1 until get to 0reduce “length” by 1 until get to 0
» NOTE: we’re just NOTE: we’re just pretendingpretending it’s smaller it’s smaller
public static void printInReverse(int[] arr, int len) {public static void printInReverse(int[] arr, int len) {
if (len > 0) {if (len > 0) { // stop if len == 0// stop if len == 0
System.out.print(arr[len - 1] + " ");System.out.print(arr[len - 1] + " ");
printInReverse(arr, len - 1);printInReverse(arr, len - 1); // “smaller” array// “smaller” array
}}
}}
Another ExampleAnother Example
To Find the Maximum Value in an ArrayTo Find the Maximum Value in an Array Base CaseBase Case
» if length is 1, the only element is the maximumif length is 1, the only element is the maximum
Recursive CaseRecursive Case» Get the maximum from the rest of the array...Get the maximum from the rest of the array...» ...& compare it to the last element...& compare it to the last element» Return the biggerReturn the bigger 6 100 3 -2 8 18 5
100 5
100
ExerciseExercise
Translate the (recursive) algorithm from the Translate the (recursive) algorithm from the previous slide into Javaprevious slide into Java Base CaseBase Case
» if length is 1, the only element is the maximumif length is 1, the only element is the maximum
Recursive CaseRecursive Case» Get the maximum from the rest of the array...Get the maximum from the rest of the array...» ...& compare it to the last element...& compare it to the last element» Return the biggerReturn the bigger
Remember to use a “pretend” length
Working From Both EndsWorking From Both Ends
Sometimes we want to be able to shorten Sometimes we want to be able to shorten the array at either endthe array at either end
Pass start and end points instead of lengthPass start and end points instead of length Done whenDone when
lo > hi (for len==0), orlo > hi (for len==0), or lo == hi (for len==1)lo == hi (for len==1)
““Sub-Array processing”Sub-Array processing”
Working From Both EndsWorking From Both Ends
Alternate way to find array maximumAlternate way to find array maximum compare first and last elementscompare first and last elements drop the smaller out of range we’re usingdrop the smaller out of range we’re using stop when array has only one element leftstop when array has only one element left
» maximum is that one elementmaximum is that one element
6 100 3 -2 8 18 5
100
Working From Both EndsWorking From Both Ends
Alternate way to find array maximumAlternate way to find array maximumpublic static int maximum(int[] arr, int lo, int hi) {public static int maximum(int[] arr, int lo, int hi) {
if (lo == hi) {if (lo == hi) {
return arr[lo];return arr[lo]; // stop!// stop!
} else if (arr[lo] > arr[hi]) {} else if (arr[lo] > arr[hi]) {
return maximum(arr, lo, hi - 1);return maximum(arr, lo, hi - 1); // smaller// smaller
} else {} else {
return maximum(arr, lo + 1, hi);return maximum(arr, lo + 1, hi); // smaller// smaller
}}
}}
Array SplittingArray Splitting
Sub-array processing can get rid of more Sub-array processing can get rid of more than one element at a timethan one element at a time
Binary split is a common methodBinary split is a common method do top “half” and bottom “half” separatelydo top “half” and bottom “half” separately combine to get answercombine to get answer
6 100 3 -2 8 18 5
100 18
100
Array SplittingArray Splitting
Alternate way to find array maximumAlternate way to find array maximumpublic static int maximum(int[] arr, int lo, int hi) {public static int maximum(int[] arr, int lo, int hi) { if (lo == hi) {if (lo == hi) { return arr[lo];return arr[lo]; // stop!// stop! } else {} else { int mid = lo + (hi - lo) / 2;int mid = lo + (hi - lo) / 2; int maxLo = maximum(arr, lo, mid); int maxLo = maximum(arr, lo, mid); // smaller!// smaller! int maxHi = maximum(arr, mid+1, hi); int maxHi = maximum(arr, mid+1, hi); // smaller!// smaller! return (maxLo > maxHi) ? maxLo : maxHi;return (maxLo > maxHi) ? maxLo : maxHi; }}}}
Array Recursion ExerciseArray Recursion Exercise
Given an array and a number, find out if the Given an array and a number, find out if the number is in the array (contains method)number is in the array (contains method) Base Case(s)Base Case(s)
» ??
Recursive Case(s)Recursive Case(s)» ??
Recursion with Linked StructuresRecursion with Linked Structures
Simple recursionSimple recursion Values get smallerValues get smaller
Recursion with arraysRecursion with arrays Array length gets smallerArray length gets smaller
Recursion with linked structuresRecursion with linked structures look at first elementlook at first element if necessary, look at the restif necessary, look at the rest
Example Linked RecursionExample Linked Recursion
To Print a Linked List in reverseTo Print a Linked List in reverse Base Case (Stop)Base Case (Stop)
» If the list is empty, do nothingIf the list is empty, do nothing
Recursive Case (Smaller)Recursive Case (Smaller)» Print the Print the restrest of the elements in reverse order of the elements in reverse order» ThenThen print the first element print the first element
5 18 8 -2 3 100 5 18 8 -2 3 100 6
6 & 100 & 3 & -2 & 8 & 18 & 5 /
Linked Structure RecursionLinked Structure Recursion
Print linked structure in reversePrint linked structure in reverse give first node to the methodgive first node to the methodprivate void printInReverse(Node first) {private void printInReverse(Node first) {
if (first != null) {if (first != null) { // stop if list is empty!// stop if list is empty!
printInReverse(first.next); printInReverse(first.next); // smaller!// smaller!
System.out.println(first.data + " ");System.out.println(first.data + " ");
}}
}}
ExerciseExercise
Write a recursive method to find whether a Write a recursive method to find whether a linked structure contains a given valuelinked structure contains a given value contains(8) contains(8) true true contains(15) contains(15) false false hint: contains(6): true or false?hint: contains(6): true or false?
6 & 100 & 3 & -2 & 8 & 18 & 5 /
Recursive Algorithm AnalysisRecursive Algorithm Analysis
Still in terms of size of problemStill in terms of size of problem size of n for factorial(n), fibonacci(n), …size of n for factorial(n), fibonacci(n), … size of array/linked structure in printInReverse, size of array/linked structure in printInReverse,
findMaximum, …findMaximum, … Base case probably just one operationBase case probably just one operation Recursive case Recursive case recursive count recursive count
amount of work for n in terms of amount of amount of work for n in terms of amount of work for n - 1work for n - 1
Work for printInReverse (Array)Work for printInReverse (Array)
N is the “length” of the array (len)N is the “length” of the array (len)public static void printInReverse(int[] arr, int len) {public static void printInReverse(int[] arr, int len) { if (len > 0) {if (len > 0) { // stop if len == 0// stop if len == 0 System.out.print(arr[len - 1] + " ");System.out.print(arr[len - 1] + " "); printInReverse(arr, len - 1);printInReverse(arr, len - 1); // “smaller” array// “smaller” array }}}}
if len == 0: compare len to 0: W(0) = 1if len == 0: compare len to 0: W(0) = 1 if len > 0: compare len to 0, print arr[len-1], call if len > 0: compare len to 0, print arr[len-1], call
printInReverse with len-1:printInReverse with len-1:» W(len) = 2 + W(len - 1)W(len) = 2 + W(len - 1)
Recurrence RelationRecurrence Relation
When W(n) defined in terms of W(n – 1)…When W(n) defined in terms of W(n – 1)… or some other smaller value than nor some other smaller value than n
… … it’s called a recurrence relationit’s called a recurrence relation It’s a recursive definition of WIt’s a recursive definition of W
has a base case (n = 0 or n = 1 or …)has a base case (n = 0 or n = 1 or …) has a recursive casehas a recursive case
Solving by InspectionSolving by Inspection
Work for printInReverse:Work for printInReverse: W(0) = 1W(0) = 1 (change)(change) W(1) = 2 + W(0) = 3W(1) = 2 + W(0) = 3 +2+2 W(2) = 2 + W(1) = 5W(2) = 2 + W(1) = 5 +2+2 W(3) = 2 + W(2) = 7W(3) = 2 + W(2) = 7 +2+2 W(4) = 2 + W(3) = 9W(4) = 2 + W(3) = 9 +2+2 …… linear: factor of 2linear: factor of 2 W(N) = 2N + 1?W(N) = 2N + 1?
Proof by InductionProof by Induction
Suppose W(n) = 2n + 1 for n < NSuppose W(n) = 2n + 1 for n < N What is W(N)?What is W(N)?
W(N) = 2 + W(N – 1)W(N) = 2 + W(N – 1) but N – 1 < N, so:but N – 1 < N, so:
» W(N – 1) = 2(N – 1) + 1 = 2N – 2 +1 = 2N – 1W(N – 1) = 2(N – 1) + 1 = 2N – 2 +1 = 2N – 1
W(N) = 2 + 2N – 1 = 2N – 1 + 2 = 2N + 1W(N) = 2 + 2N – 1 = 2N – 1 + 2 = 2N + 1 so W(N) so W(N) alsoalso = 2N + 1 = 2N + 1 and that’s for and that’s for anyany N > 0 N > 0
Array SplittingArray Splitting
public static int maximum(int[] arr, int lo, int hi) {public static int maximum(int[] arr, int lo, int hi) { if (lo == hi) {if (lo == hi) { // 1 comparison// 1 comparison return arr[lo];return arr[lo]; // 1 array access// 1 array access } else {} else { int mid = lo + (hi - lo) / 2;int mid = lo + (hi - lo) / 2; // 3 math ops// 3 math ops int maxLo = maximum(arr, lo, mid);int maxLo = maximum(arr, lo, mid); // 1 asgn + REC// 1 asgn + REC int maxHi = maximum(arr, mid+1, hi);int maxHi = maximum(arr, mid+1, hi); // 1 asgn + REC// 1 asgn + REC return (maxLo > maxHi) ? maxLo : maxHi;return (maxLo > maxHi) ? maxLo : maxHi; // 1 comparison// 1 comparison }}}}W(1) = 2W(1) = 2 +W / +N+W / +NW(2) = 6 + 2W(1) = 6 + 2(2) = 10W(2) = 6 + 2W(1) = 6 + 2(2) = 10 + 8 / +1+ 8 / +1 8N – 68N – 6W(4) = 6 + 2W(2) = 6 + 2(10) = 26W(4) = 6 + 2W(2) = 6 + 2(10) = 26 +16 / +2+16 / +2 8N – 68N – 6W(8) = 6 + 2W(4) = 6 + 2(26) = 58W(8) = 6 + 2W(4) = 6 + 2(26) = 58 +32 / +4+32 / +4 8N – 68N – 6W(16) = 6 + 2W(8) = 6 + 2(58) = 122W(16) = 6 + 2W(8) = 6 + 2(58) = 122 +64 / +8+64 / +8 8N – 68N – 6
findMaximum by SplittingfindMaximum by Splitting
Split array into two (nearly equal) partsSplit array into two (nearly equal) parts look at only powers of 2look at only powers of 2
» even splits all the way downeven splits all the way down
looks like W(N) = 8N – 6looks like W(N) = 8N – 6» linearlinear
» works for N <= 16works for N <= 16
do induction on 2N instead of N+1do induction on 2N instead of N+1 (later we’ll do 2N+1)(later we’ll do 2N+1)
Proof by Induction (Part 1)Proof by Induction (Part 1)
Assume W(n) = 8n – 6 for n < 2NAssume W(n) = 8n – 6 for n < 2N What’s W(2N)?What’s W(2N)?
W(2N) = 6 + 2W(N)W(2N) = 6 + 2W(N) but N < 2N, so W(N) = 8N – 6…but N < 2N, so W(N) = 8N – 6… … … so W(2N) = 6 + 2(8N–6)so W(2N) = 6 + 2(8N–6)
= 6 + 16N – 12 = 6 + 16N – 12 = 16N – 6 = 16N – 6 = 8(2N) – 6 = 8(2N) – 6
same formula works for all same formula works for all eveneven N N
Proof by Induction (Part 2)Proof by Induction (Part 2)
Assume W(n) = 8n – 6 for n < 2NAssume W(n) = 8n – 6 for n < 2N What’s W(2N + 1)?What’s W(2N + 1)?
W(2N + 1) = 6 + W(N) + W(N+1)W(2N + 1) = 6 + W(N) + W(N+1) but N < N+1 < 2N, so …but N < N+1 < 2N, so … W(2N + 1) = 6 + (8N – 6) + (8(N+1) – 6) W(2N + 1) = 6 + (8N – 6) + (8(N+1) – 6)
= 6 + 8N – 6 + 8N + 8 – 6 = 6 + 8N – 6 + 8N + 8 – 6 = 16N + 8 – 6 = 16N + 8 – 6 = 8(2N+1) – 6 = 8(2N+1) – 6
same formula works for all same formula works for all oddodd N N
Towers of HanoiTowers of Hanoi
N = number of disksN = number of disks Work = number of movesWork = number of moves
W(0) = 0W(0) = 0 (change)(change) W(1) = W(0) + 1 + W(0) = 1W(1) = W(0) + 1 + W(0) = 1 +1+1 W(2) = W(1) + 1 + W(1) = 3W(2) = W(1) + 1 + W(1) = 3 +2+2 W(3) = W(2) + 1 + W(2) = 7W(3) = W(2) + 1 + W(2) = 7 +4+4 W(4) = W(3) + 1 + W(3) = 15W(4) = W(3) + 1 + W(3) = 15 +8+8 W(5) = W(4) + 1 + W(4) = 31W(5) = W(4) + 1 + W(4) = 31 +16+16
Solve by InspectionSolve by Inspection
Work doubles at each step of NWork doubles at each step of N sounds exponentialsounds exponential compare work with 2compare work with 2NN
22NN = W(N) + 1 = W(N) + 1 so work = 2so work = 2NN – 1 – 1 exponentialexponential
N W(N) 2N
0 0 1
1 1 2
2 3 4
3 7 8
4 15 16
5 31 32
N 2N – 1 2N
Proof by InductionProof by Induction
Assume W(n) = 2Assume W(n) = 2nn – 1 for n < N – 1 for n < N What’s W(N)?What’s W(N)?
W(N) = 1 + 2W(N–1)W(N) = 1 + 2W(N–1)
= 1 + 2(2= 1 + 2(2N–1N–1 – 1) – 1)
= 1 + 2= 1 + 2NN – 2 – 2
= 2= 2NN – 1 – 1 formula works for all Nformula works for all N
ExerciseExercise
How much work is done by printInReverse How much work is done by printInReverse for the for the linkedlinked structure? structure?private void printInReverse(Node first) {private void printInReverse(Node first) { if (first != null) {if (first != null) { // stop if list is empty!// stop if list is empty! printInReverse(first.next); printInReverse(first.next); // smaller!// smaller! System.out.println(first.data + " ");System.out.println(first.data + " "); }}}}
write recurrence relationwrite recurrence relation solve order of magnitudesolve order of magnitude
Bad RecursionBad Recursion
Recursion often shorter than loopsRecursion often shorter than loops especially when double recursion is neededespecially when double recursion is needed
» like in towers of Hanoi problemlike in towers of Hanoi problem
Recursion usually same complexity as loopsRecursion usually same complexity as loops but NOT ALWAYSbut NOT ALWAYS especially if you get double recursionespecially if you get double recursion
Fibonacci RecursionFibonacci Recursion
Fibonacci uses double recursionFibonacci uses double recursion count number of additions requiredcount number of additions requiredpublic static int fibonacci(int n) {public static int fibonacci(int n) { if (n <= 1) return 1;if (n <= 1) return 1; else return fibonacci(n-1) else return fibonacci(n-1) ++ fibonacci(n-2); fibonacci(n-2);}}
» W(0) = W(1) = 0W(0) = W(1) = 0» W(2) = 1 + W(1) + W(0) = 1 + 0 + 0 = 1W(2) = 1 + W(1) + W(0) = 1 + 0 + 0 = 1 +1+1» W(3) = 1 + W(2) + W(1) = 1 + 1 + 0 = 2W(3) = 1 + W(2) + W(1) = 1 + 1 + 0 = 2 +1+1» W(4) = 1 + W(3) + W(2) = 1 + 2 + 1 = 4W(4) = 1 + W(3) + W(2) = 1 + 2 + 1 = 4 +2+2» W(5) = 1 + W(4) + W(3) = 1 + 4 + 2 = 7W(5) = 1 + W(4) + W(3) = 1 + 4 + 2 = 7 +3+3» W(6) = 1 + W(5) + W(4) = 1 + 7 + 4 = 12W(6) = 1 + W(5) + W(4) = 1 + 7 + 4 = 12 +5+5
Too ComplicatedToo Complicated
Assume that the work is increasingAssume that the work is increasing standard assumptionstandard assumption
Thus W(N-1) > W(N-2)Thus W(N-1) > W(N-2) Thus 1 + W(N-1) + W(N-2) > 1 + 2W(N-2)Thus 1 + W(N-1) + W(N-2) > 1 + 2W(N-2) So let’s solve that recurrence relationSo let’s solve that recurrence relation
work for fibonacci will be work for fibonacci will be worseworse than that than that
Simplified EquationsSimplified Equations
Using W(N) = 1 + 2W(N-2)Using W(N) = 1 + 2W(N-2)» W(0) = 0W(0) = 0 W(1) = 0W(1) = 0» W(2) = 1 + 2W(0) = 1 + 2(0) = 1W(2) = 1 + 2W(0) = 1 + 2(0) = 1 W(3) = 1 + 2W(1) = 1W(3) = 1 + 2W(1) = 1» W(4) = 1 + 2W(2) = 1 + 2(1) = 3W(4) = 1 + 2W(2) = 1 + 2(1) = 3 W(5) = 1 + 2W(3) = 3W(5) = 1 + 2W(3) = 3» W(6) = 1 + 2W(4) = 1 + 2(3) = 7W(6) = 1 + 2W(4) = 1 + 2(3) = 7 W(7) = 1 + 2W(5) = 7W(7) = 1 + 2W(5) = 7» W(8) = 1 + 2W(6) = 1 + 2(7) = 15W(8) = 1 + 2W(6) = 1 + 2(7) = 15 W(9) = 1 + 2W(7) = 15W(9) = 1 + 2W(7) = 15» W(10) = 1 + 2W(8) = 1 + 2(15) = 31W(10) = 1 + 2W(8) = 1 + 2(15) = 31 ……
similar to towers of Hanoi: W(N) = 2similar to towers of Hanoi: W(N) = 2NN – 1 – 1 but here a bit smaller: W(N) = 2but here a bit smaller: W(N) = 2N/2N/2 – 1 – 1 but but stillstill exponential exponential
» and work for fibonacci is and work for fibonacci is worseworse
Can We Do Better?Can We Do Better?
For Fibonacci? Yes! We can do O(N)For Fibonacci? Yes! We can do O(N)int f1 = 1, f2 = 1; int f1 = 1, f2 = 1; while (n > 1) { while (n > 1) {
int f3 = f1 + f2; int f3 = f1 + f2; f1 = f2; f1 = f2; f2 = f3; f2 = f3; --n;--n;
} } return f2;return f2;
For towers of Hanoi? No!For towers of Hanoi? No! the number of moves required is exponentialthe number of moves required is exponential there’s no way to do better than thatthere’s no way to do better than that
QuestionsQuestions