In Class: Week 10
Recursion


Create a subdirectory in your cs21/inclass directory by running update21:

$ update21
$ cd
$ cd cs21/inclass/w10-recursion

Topics


In-class work

Recursion

  1. Open simpleRecursion.py. We are going to write some iterative and recursive versions of the same function. Iterative versions use loops, recursive versions do not use loops, and instead contain calls to themselves but on a smaller problem. The idea of recursive functions is based on recursive definitions. For example, n! can be defined as n(n-1)!.

    1. Lets try writing sum of ints together
    2. Next, try writing an iterative version (using a loop) of factorial that takes a positive int value, n, and returns the product of the first n integers.
    3. Next, try writing a recursive version of the factorial function.

  2. For any recursive problem, think of three questions:
    1. What is the base case? That is, in what instances can I stop recursing because we know the answer?
    2. What is the recursive call? Make one or calls in the function to itself. It is very important to use different arguments (usually "smaller") in the recursive call otherwise you obtain infinite recursion.
    3. Do all possible chains of recursion lead to a base case?
  3. Next, we will work on recursive algorithms for strings and lists. Open up listStringRecursion.py and write two functions. First, we will write a function that checks if a word is a palindrome. A palindrome is any word that reads the same forward as backwards. Or, to put another, the second half is a mirror of the first half. For example, "hello" is not a palindrome, but "racecar" and "otto" are.

  4. In constructSequence(), we will create a sequence of integers from 1 through n using recursion. There are some languages completely built off this method (as opposed to iteration).

  5. Recursion plays in important role in mathematics and graphical representations of seemingly complex objects. We will revisit our bulls eye graphics example from early in the course to define a recursive solution to the problem in recursiveCircle.py. (Note: this was skipped to talk more generally about fractals).

  6. Recursive functions can have more than one different recursive call within the function. For example, let us work out how we can recursively define binary search, which recursively calls binary search on one-half of the problem. We will code our solution in binarySearch.py

    Merge Sort

  7. Last week, we looked at several sorting algorithms, all of which had O(N^2) runtime. We will take a look at merge sort, a divide-and-conquer algorithm with a similar pattern to binary search in that we divide our problem in half successively into we reach small lists that are easy to sort.

  8. First, in partners, come up with an algorithm to combine two already sorted lists into one. This is similar to the merge step in merge sort.

  9. Next, let's code up our solution for merge and our recursive definition for merge sort in mergesort.py.

  10. When we analyze the run time of merge sort, we notice that on any level of the recursion, the total amount of work being down by all of the merges is O(N). That is, to combine two lists of size N/2, it takes O(N) time. Similarly, combining two N/4 lists and combining another two N/4 lists takes O(N) time in total. The next question is, how many levels are there in merge sort? Since divide-and-conquer divides the problem in half each time, we see that it takes O(lgN) recursions to reach the base case, meaning that we do O(N) work a total of O(lg N) times resulting in an O(N lg N) algorithm.