Page 1
RECURSION FOR THE REST OF US
CS FUNDAMENTALS SERIES
http://bit.ly/29zaKm3
Page 2
WHAT IS RECURSION?
Page 3
THIS IS RECURSION.
Page 5
RECURSION IS JUST A FUNCTION THAT CALLS
ITSELF.
Page 6
WHY WOULD A FUNCTION CALL ITSELF?
Page 7
A RECURSIVE FUNCTION CALLS ITSELF BECAUSE
IT’S RECURSIVE.
Page 8
SERIOUSLY. WHEN WOULD YOU WANT
TO USE RECURSION?
Page 9
NAMELY: WHEN A PROBLEM CAN BE
EASILY DEFINED IN TERMS OF SUBPROBLEMS.
Page 10
QUINTESSENTIAL EXAMPLE:FACTORIAL!
Page 11
5! = 5 * 4 * 3 * 2 * 1
Page 12
4! = 4 * 3 * 2 * 1
5! = 5 * 4 * 3 * 2 * 1
Page 14
You can easily express factorial in terms of subproblems.
Specifically, if you have the subproblem
(N - 1)! you can easily get
N!
Page 15
N! = N * (N - 1)!
Page 17
ONLY ONE PROBLEM…
Page 22
WE NEED TO TELL THE SNAKE WHEN TO BITE DOWN
AND STOP RECURSING.
Page 23
LET’S JUST SAY: 0! = 1
Page 24
1! = 1 * 0!
1! = 1 * 1
Page 25
SO WITH THAT, 1! = 1
Page 26
2! = 2 * 1! 3! = 3 * 2! 4! = 4 * 3! 5! = 5 * 4!
= 2= 6= 24= 120
Page 27
WE NEEDED TWO THINGS TO GET THE RECURSIVE
ALGORITHM.
Page 28
N * (N - 1)!
First, we need to know how to solve the problem of size N in terms of smaller subproblems.
This is also called the inductive step.
(See: induction)
Page 29
0! = 1 Second, we need the base case.
The recursion has to end somewhere, so we just hard-code it in.
Page 30
AND THAT’S ALL THERE IS TO IT.
Page 31
WORDS OF WARNING
▸ Recursion is often weird and unintuitive.
▸ Don’t try to do something recursively that’s better done iteratively!
▸ But there are times when it’s the most elegant way to solve a problem.
▸ E.g., factorial, sorting, many tree and graph problems (or generally when using any recursive data structure).
Page 32
DEBUGGING RECURSION
▸ Recursion is usually more difficult to debug.
▸ If you don’t define your base case properly, you’ll usually trigger a stack overflow.
Page 33
DEBUGGING RECURSION
▸ Console.log is your friend.
▸ Recursion usually works not at all, or everything works at once. This makes it trickier to introspect.
▸ Consider using: if (condition) debugger;
Page 34
SIMPLE EXAMPLE function sum(arr)
Page 35
MORE RECURSION ADVICE
▸ Start with the inductive step.
▸ Don’t go straight into coding it, first map it out and make sure you understand it.
▸ Then enter in the base case.
▸ Usually if you’re hard-coding multiple base cases, you’re overcomplicating it.
Page 36
TIPS ON GENERATING THE INDUCTIVE STEP
▸ First, think about what a subproblem would look like. How can I make the input smaller?
▸ Is it size N - 1? N - 3? N / 2? All of these are valid subproblem sizes; what would make the solution easy?
▸ Think of recursion like cheating…
Page 37
PRETEND YOU SMUGGLED IN AN ALGORITHM THAT ALREADY
SOLVES THE PROBLEM
Page 38
BUT ONLY FOR SIZE N - 1…
Page 39
HOW WOULD YOU USE THAT ALGORITHM TO GENERATE THE ANSWER FOR SIZE N?
Page 40
FINALLY, JUST HARD-CODE IN A BASE CASE.
Page 41
TA-DA! SPECS PASSING.
Page 42
BASICALLY, RECURSION IS MAGIC.
Page 44
HARDER EXAMPLES function triplets(arr)
function join(strings, separator)
Page 45
OKAY, LET’S DO SOME RECURSION.
Page 46
SO WHAT’S THIS MAXIMUM CALL STACK
SIZE EXCEEDED
BUSINESS?
Page 48
FIRST, WE NEED TO UNDERSTAND HOW
FUNCTION CALLING WORKS.
Page 50
fn:one line 17LocalVariablesTHE STACK:
Page 51
fn:one line 17LocalVariables
THE STACK:fn:two line 22Local
Variables
Page 52
fn:one line 17LocalVariables
THE STACK:fn:two line 22Local
Variables
fn:three line 27LocalVariables
>> Finished function 3.
Page 53
fn:one line 17LocalVariables
THE STACK:fn:two line 22Local
Variables
fn:three line 28LocalVariables
Page 54
fn:one line 17LocalVariables
THE STACK:fn:two line 22Local
Variables
fn:three line 28LocalVariables
Page 55
fn:one line 17LocalVariables
fn:two line 22LocalVariables
fn:three line 28LocalVariables
Page 56
NOW WE POP FROM THE STACK.
Page 57
fn:one line 17LocalVariables
fn:two line 22LocalVariables
fn:three line 28Local
Variables
Page 58
fn:one line 17LocalVariables
THE STACK:fn:two line 22Local
Variables
Page 59
fn:one line 17LocalVariables
THE STACK:fn:two line 23Local
Variables
>> Done with function 2.
Page 60
fn:one line 17LocalVariables
THE STACK:
fn:twoline 23
LocalVariables
Page 61
fn:one line 17LocalVariables
THE STACK:
Page 62
fn:one line 17LocalVariables
THE STACK:
>> And done with function 1!
Page 63
SO HOW CAN WE BREAK THIS?
Page 65
fn:one line 17LocalVariables
fn:two line 22LocalVariables
fn:three line 28LocalVariables
THE STACK:
fn:one line 17LocalVariables
Page 66
fn:one line 17LocalVariables
fn:two line 22LocalVariables
fn:three line 28LocalVariables
THE STACK:
fn:one line 17LocalVariables
fn:two line 22LocalVariables
Page 67
fn:one line 17LocalVariables
fn:two line 22LocalVariables
fn:three line 28LocalVariables
THE STACK:
fn:one line 17LocalVariables
fn:two line 22LocalVariables
fn:three line 28LocalVariables
Page 68
fn:one line 17LocalVariables
fn:two line 22LocalVariables
fn:three line 28LocalVariables
THE STACK:
fn:one line 17LocalVariables
fn:two line 22LocalVariables
fn:three line 28LocalVariables
fn:one line 17LocalVariables
Page 70
EVENTUALLY, WE RUN OUT OF MEMORY
(OR SPACE ON THE STACK).
Page 73
THIS IS WHY RECURSIVE ALGORITHMS CAN’T
INFINITE LOOP*
* Without tail recursion or explicit loops
Page 74
AND THIS IS ALSO WHY RECURSION IS SOMETIMES LESS
SPACE-EFFICIENT THAN ITERATION
Page 75
EACH STACK FRAME HAS TO BE HELD IN MEMORY
Page 76
AND GETS EVALUATED ONE BY ONE.
Page 77
IT’S ALSO TRUE THAT EVERY RECURSIVE ALGORITHM
IMPLICITLY USES A STACK
Page 78
SO IF YOU WANT TO IMPLEMENT A RECURSIVE ALGORITHM
ITERATIVELY, YOU OFTEN NEED TO MANAGE YOUR OWN STACK.
Page 80
SO HOW DO YOU CALCULATE THE BIG O OF A RECURSIVE ALGORITHM?
Page 81
Number of stack frames
*
average runtime per stack frame
Page 82
IT GETS MORE COMPLICATED THAN THAT, BUT THAT’S A GOOD STARTING POINT.(SEE MASTER METHOD, RECURRENCES,
RECURSION TREES, ETC.)
Page 83
DEMO RECURSIVE RUNTIME ANALYSIS
Page 86
I AM HASEEB QURESHI
You can find me on Twitter: @hosseeb
You can read my blog at: haseebq.com
Page 87
PLEASE DONATE IF YOU GOT SOMETHING OUT OF THIS
<3
Ranked by GiveWell as the most
efficient charity in the world!