87
RECURSION FOR THE REST OF US CS FUNDAMENTALS SERIES http://bit.ly/29zaKm3

Recursion For the Rest of Us (CS Fundamentals Series)

Embed Size (px)

Citation preview

RECURSION FOR THE REST OF US

CS FUNDAMENTALS SERIES

http://bit.ly/29zaKm3

WHAT IS RECURSION?

THIS IS RECURSION.

SO IS THIS.

RECURSION IS JUST A FUNCTION THAT CALLS

ITSELF.

WHY WOULD A FUNCTION CALL ITSELF?

A RECURSIVE FUNCTION CALLS ITSELF BECAUSE

IT’S RECURSIVE.

SERIOUSLY. WHEN WOULD YOU WANT

TO USE RECURSION?

NAMELY: WHEN A PROBLEM CAN BE

EASILY DEFINED IN TERMS OF SUBPROBLEMS.

QUINTESSENTIAL EXAMPLE:FACTORIAL!

5! = 5 * 4 * 3 * 2 * 1

4! = 4 * 3 * 2 * 1

5! = 5 * 4 * 3 * 2 * 1

5! = 5 * 4!

You can easily express factorial in terms of subproblems.

Specifically, if you have the subproblem

(N - 1)! you can easily get

N!

N! = N * (N - 1)!

EASY, RIGHT?

ONLY ONE PROBLEM…

2! = 2 * 1!

1! = 1 * 0!

0! = 0 * -1! …

WE NEED TO TELL THE SNAKE WHEN TO BITE DOWN

AND STOP RECURSING.

LET’S JUST SAY: 0! = 1

1! = 1 * 0!

1! = 1 * 1

SO WITH THAT, 1! = 1

2! = 2 * 1! 3! = 3 * 2! 4! = 4 * 3! 5! = 5 * 4!

= 2= 6= 24= 120

WE NEEDED TWO THINGS TO GET THE RECURSIVE

ALGORITHM.

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)

0! = 1 Second, we need the base case.

The recursion has to end somewhere, so we just hard-code it in.

AND THAT’S ALL THERE IS TO IT.

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).

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.

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;

SIMPLE EXAMPLE function sum(arr)

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.

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…

PRETEND YOU SMUGGLED IN AN ALGORITHM THAT ALREADY

SOLVES THE PROBLEM

BUT ONLY FOR SIZE N - 1…

HOW WOULD YOU USE THAT ALGORITHM TO GENERATE THE ANSWER FOR SIZE N?

FINALLY, JUST HARD-CODE IN A BASE CASE.

TA-DA! SPECS PASSING.

BASICALLY, RECURSION IS MAGIC.

HARDER EXAMPLES function triplets(arr)

function join(strings, separator)

OKAY, LET’S DO SOME RECURSION.

SO WHAT’S THIS MAXIMUM CALL STACK

SIZE EXCEEDED

BUSINESS?

FIRST, WE NEED TO UNDERSTAND HOW

FUNCTION CALLING WORKS.

fn:one line 17LocalVariablesTHE STACK:

fn:one line 17LocalVariables

THE STACK:fn:two line 22Local

Variables

fn:one line 17LocalVariables

THE STACK:fn:two line 22Local

Variables

fn:three line 27LocalVariables

>> Finished function 3.

fn:one line 17LocalVariables

THE STACK:fn:two line 22Local

Variables

fn:three line 28LocalVariables

fn:one line 17LocalVariables

THE STACK:fn:two line 22Local

Variables

fn:three line 28LocalVariables

fn:one line 17LocalVariables

fn:two line 22LocalVariables

fn:three line 28LocalVariables

NOW WE POP FROM THE STACK.

fn:one line 17LocalVariables

fn:two line 22LocalVariables

fn:three line 28Local

Variables

fn:one line 17LocalVariables

THE STACK:fn:two line 22Local

Variables

fn:one line 17LocalVariables

THE STACK:fn:two line 23Local

Variables

>> Done with function 2.

fn:one line 17LocalVariables

THE STACK:

fn:twoline 23

LocalVariables

fn:one line 17LocalVariables

THE STACK:

fn:one line 17LocalVariables

THE STACK:

>> And done with function 1!

SO HOW CAN WE BREAK THIS?

fn:one line 17LocalVariables

fn:two line 22LocalVariables

fn:three line 28LocalVariables

THE STACK:

fn:one line 17LocalVariables

fn:one line 17LocalVariables

fn:two line 22LocalVariables

fn:three line 28LocalVariables

THE STACK:

fn:one line 17LocalVariables

fn:two line 22LocalVariables

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

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

THE STACK:

EVENTUALLY, WE RUN OUT OF MEMORY

(OR SPACE ON THE STACK).

AND WE GET A…

THIS IS WHY RECURSIVE ALGORITHMS CAN’T

INFINITE LOOP*

* Without tail recursion or explicit loops

AND THIS IS ALSO WHY RECURSION IS SOMETIMES LESS

SPACE-EFFICIENT THAN ITERATION

EACH STACK FRAME HAS TO BE HELD IN MEMORY

AND GETS EVALUATED ONE BY ONE.

IT’S ALSO TRUE THAT EVERY RECURSIVE ALGORITHM

IMPLICITLY USES A STACK

SO IF YOU WANT TO IMPLEMENT A RECURSIVE ALGORITHM

ITERATIVELY, YOU OFTEN NEED TO MANAGE YOUR OWN STACK.

COOL.

SO HOW DO YOU CALCULATE THE BIG O OF A RECURSIVE ALGORITHM?

Number of stack frames

*

average runtime per stack frame

IT GETS MORE COMPLICATED THAN THAT, BUT THAT’S A GOOD STARTING POINT.(SEE MASTER METHOD, RECURRENCES,

RECURSION TREES, ETC.)

DEMO RECURSIVE RUNTIME ANALYSIS

QUESTIONS?

I AM HASEEB QURESHI

You can find me on Twitter: @hosseeb

You can read my blog at: haseebq.com

PLEASE DONATE IF YOU GOT SOMETHING OUT OF THIS

<3

Ranked by GiveWell as the most

efficient charity in the world!