Example: Sum the digits i a umber /** retur sum of digits i, give >= 0 */ public static it sum(it ) { if ( < 0) retur ; sum calls itself! // has at least two digits: // retur first digit + sum of rest retur %0 + sum(/0); Lecture 6 CS0 Sprig 03 RECURSION E.g. sum(870) = +(+(0+(7+8))) 8 Recursio Arises i three forms i computer sciece Recursio as a mathematical tool for defiig a fuctio i terms of its ow value i a simpler case Recursio as a programmig tool. You ve see this previously but we ll take it to mid-bedig extremes (by the ed of the class it will seem easy!) 5 Example: Is a strig a palidrome? /** = "s is a palidrome" */ public static boolea ispalidrome(strig s) { if (s.legth() <) retur true; Substrig from char() to char(-) // s has at least chars it = s.legth()-; retur s.charat(0) == s.charat() && ispalidrome(s.substrig(, )); Recursio used to prove properties about algorithms. We use the term iductio for this ad will discuss it later. ispalidrome( racecar ) = true ispalidrome( pumpki ) = false r a c e c a r a c e c a c e c e 3 Recursio as a math techique Broadly, recursio is a powerful techique for specifyig fuctios, sets, ad programs A few recursively-defied fuctios ad programs factorial combiatios expoetiatio (raisig to a iteger power) Some recursively-defied sets grammars expressios data structures (lists, trees,...) 6 Cout the e s i a strig /** = " umber of times c occurs i s */ public static it coutem(char c, Strig s) { if (s.legth() == 0) retur 0; // { s has at least character if (s.charat(0)!= c) retur coutem(c, s.substrig()); // { first character of s is c retur + coutem (c, s.substrig()); coutem( e, it is easy to see that this has may e s ) = coutem( e, Mississippi ) = 0 Substrig from char() to ed
The Factorial Fuctio (!) Observatio 7 0 Defie! = () () 3 read: factorial E.g., 3! = 3 = 6 By covetio, 0! The fuctio it it that gives! o iput is called the factorial fuctio Oe way to thik about the task of permutig the four colored blocks was to start by computig all permutatios of three blocks, the fidig all ways to add a fourth block Ad this explais why the umber of permutatios turs out to be! Ca geeralize to prove that the umber of permutatios of blocks is! The Factorial Fuctio (!) A Recursive Program 8! is the umber of permutatios of distict objects There is just oe permutatio of oe object.! There are two permutatios of two objects:! = There are six permutatios of three objects: 3! = 6 3 3 3 3 3 3 If > 0,! = ( )! 0!! = ()!, > 0 static it fact(it ) { if ( = = 0) retur ; else retur *fact(-); Executio of fact() fact() fact(3) fact() fact() fact(0) 6 Permutatios of Geeral Approach to Writig Recursive Fuctios 9 Permutatios of o-orage blocks. Try to fid a parameter, say, such that the solutio for ca be obtaied by combiig solutios to the same problem usig smaller values of (e.g., (-) i our factorial example). Fid base case(s) small values of for which you ca just write dow the solutio (e.g., 0! ) Each permutatio of the three oorage blocks gives four permutatios whe the orage block is icluded 3. Verify that, for ay valid value of, applyig the reductio of step repeatedly will ultimately hit oe of the base cases Total umber = 3! = 6 = :!
3 A cautioary ote Keep i mid that each istace of your recursive fuctio has its ow local variables Also, remember that higher istaces are waitig while lower istaces ru Not such a good idea to touch global variables from withi recursive fuctios Legal but a commo source of errors Must have a really clear metal picture of how recursio is performed to get this right! 6 Oe thig to otice This way of computig the Fiboacci fuctio is elegat, but iefficiet It recomputes aswers agai ad agai! To improve speed, eed to save kow aswers i a table! fib() Oe etry per aswer fib() fib(3) Such a table is called a cache fib(0) fib() fib() fib() fib(0) fib() The Fiboacci Fuctio Memoizatio (facy term for cachig ) Mathematical defiitio: fib(0) = 0 two base cases! fib() fib() = fib( ) + fib( ), Fiboacci sequece: 0,,,, 3, 5, 8, 3, static it fib(it ) { if ( == 0) retur 0; else if ( =) retur ; else retur fib(-) + fib(-); Fiboacci (Leoardo Pisao) 700? Statue i Pisa, Italy Giovai Pagaucci 863 7 Memoizatio is a optimizatio techique used to speed up computer programs by havig fuctio calls avoid repeatig the calculatio of results for previously processed iputs. The first time the fuctio is called, we save result The ext time, we ca look the result up Assumes a side effect free fuctio: The fuctio just computes the result, it does t chage thigs If the fuctio depeds o aythig that chages, must empty the saved results list 5 Recursive Executio static it fib(it ) { if ( == 0) retur 0; else if ( =) retur ; else retur fib(-) + fib(-); Executio of fib(): fib(0) fib() fib() fib() fib() fib(3) fib(0) fib() fib() 8 Addig Memoizatio to our solutio Before: After static ArrayList<Iteger> cached = ew ArrayList<Iteger>(); static it fib(it ) { if ( == 0) static it fib(it ) { retur 0; if( < cached.size()) else if ( =) retur cached.get(); retur ; it v; else if ( == 0) retur fib(-) + fib(-); v = 0; else if ( =) v ; else v = fib(-) + fib(-); // cached[] = fib(). This code makes use of the fact // that a ArrayList adds elemets to the ed of the list if( == cached.size()) cached.add(v); retur v; 3
9 Notice the developmet process We started with the idea of recursio Created a very simple recursive procedure Noticed it will be slow, because it wastefully recomputes the same thig agai ad agai So made it a bit more complex but gaied a lot of speed i doig so This is a commo software egieerig patter A Smarter Versio Power computatio: a0 If is ozero ad eve, a = (a/) If is odd, a = a (a/) Java ote: If x ad y are itegers, x/y returs the iteger part of the quotiet Example: a5 = a (a5/) = a (a) = a ((a/)) = a (a) Note: this requires 3 multiplicatios rather tha 5! Why did it work? A Smarter Versio 0 This cached list works because for each value of, either cached.get() is still udefied, or has fib() Takes advatage of the fact that a ArrayList adds elemets at the ed, ad idexes from 0 cached@ba8900, size=5 0 3 cached.get(0)=0 cached.get()= cached.get()=fib() Property of our code: cached.get() accessed after fib() computed 3 Example: a5 = a (a5/) = a (a) = a ((a/)) = a (a) Note: this requires 3 multiplicatios rather tha 5! What if were larger? Savigs would be more sigificat This is much faster tha the straightforward computatio Straightforward computatio: multiplicatios Smarter computatio: log() multiplicatios Positive Iteger Powers a = a a a a ( times) Alterate descriptio: a 0 a + = a a static it power(it a, it ) { if ( == 0) retur ; else retur a*power(a,-); Smarter Versio i Java = 0: a 0 ozero ad eve: a = (a / ) ozero ad odd: a = a (a / ) local variable parameters static it power(it a, it ) { if ( == 0) retur ; it halfpower = power(a,/); if (% == 0) retur halfpower*halfpower; retur halfpower*halfpower*a; The method has two parameters ad a local variable Why are t these overwritte o recursive calls?
How Java compiles recursive code Example: power(, 5) 5 Key idea: Java uses a stack to remember parameters ad local variables across recursive calls Each method ivocatio gets its ow stack frame A stack frame cotais storage for Local variables of method Parameters of method Retur ifo (retur address ad retur value) Perhaps other bookkeepig ifo 8 hp: short for halfpower ( = ) 5 ( = ) ( = ) 5 ( = ) ( = ) ( = ) 5 (retval = ) (hp = ) ( = ) ( = ) ( = ) 5 (retval = ) (hp = ) ( = ) ( = ) 5 (retval = ) (hp = ) ( = ) 5 (retval = ) 3 6 Stacks 9 How Do We Keep Track? stack grows top elemet d elemet 3rd elemet...... bottom elemet top-of-stack poiter Like a stack of dier plates You ca push data o top or pop data off the top i a LIFO (last-i-first-out) fashio A queue is similar, except it is FIFO (first-i-first-out) May frames may exist, but computatio is oly occurrig i the top frame The oes below it are waitig for results The hardware has ice support for this way of implemetig fuctio calls, ad recursio is just a kid of fuctio call 7 Stack Frame A ew stack frame is pushed with each recursive call The stack frame is popped whe the method returs Leavig a retur value (if there is oe) o top of the stack a stack frame halfpower local variables a, parameters retval 30 Coclusio Recursio is a coveiet ad powerful way to defie fuctios Problems that seem isurmoutable ca ofte be solved i a divide-ad-coquer fashio: Reduce a big problem to smaller problems of the same kid, solve the smaller problems Recombie the solutios to smaller problems to form solutio for big problem Importat applicatio (ext lecture): parsig 5
3 Extra slides 3 Biomial Coefficiets For use if we have time for oe more example of recursio This builds o the ideas i the Fiboacci example Combiatios are also called biomial coefficiets because they appear as coefficiets i the expasio of the biomial power (x+y) : (x + y) = x + x y + x y ( 0 ) ( ) + + ( ) y = ( i ) x i y i i= 0 3 Combiatios (a.k.a. Biomial Coefficiets) Combiatios Have Two Base Cases 3 How may ways ca you choose r items from a set of distict elemets? ( ) choose r r 5 ( ) = umber of -elemet subsets of {A,B,C,D,E -elemet subsets cotaiig A: {A,B, {A,C, {A,D, {A,E ( ) -elemet subsets ot cotaiig A: {B,C,{B,D,{B,E,{C,D,{C,E,{D,E Therefore, 5 = + ( ) i perfect form to write a recursive fuctio! 35 ( r ) = ( r ) + ( r ), > r > 0 ( ) Two base cases Comig up with right base cases ca be tricky! Geeral idea: Determie argumet values for which recursive case does ot apply Itroduce a base case for each oe of these 33 Combiatios ( r ) = ( r ) + ( r ), > r > 0 ( ) 0 ( ) ( ) 3 3 3 3 ( ) ( 3) ( ) ( 3) Ca also show that ( r ) = ( ) Pascal s triagle =! r!(r)! 3 3 6 36 Recursive Program for Combiatios ( r ) = ( r ) + ( r ), > r > 0 ( ) static it combs(it, it r) { //assume >=r>=0 if (r == 0 r == ) retur ; //base cases else retur combs(-,r) + combs(-,r-); 6
Exercise for the reader (you!) 37 Modify our recursive program so that it caches results Same idea as for our cachig versio of the fiboacci series Questio to poder: Whe is it worthwhile to addig cachig to a recursive fuctio? Certaily ot always Must thik about tradeoffs: space to maitai the cached results vs speedup obtaied by havig them Somethig to thik about 38 With fib(), it was kid of a trick to arrage that: cached[]=fib() Cachig combiatorial values will force you to store more tha just the aswer: Create a class called Triple Desig it to have iteger fields, r, v Store Triple objects ito ArrayList<Triple> cached; Search cached for a saved value matchig ad r Hit: use a foreach loop 7