Jed Rembold
December 1, 2025
3198345-61d515c2On last Monday we looked at the selection sort, which had the following form:
def selection_sort(array):
for lh in range(len(array)):
rh = lh
for i in range(lh+1, len(array)):
if array[i] < array[rh]:
rh = i
array[lh], array[rh] = array[rh], array[lh]
L = [3,2,6,1]
selection_sort(L)
How many times would line 5 be reached in sorting the shown list
L?
The factorial function can be defined in two different ways, one of which lends itself nicely to recursion \[n! = (n-1) \times (n-2) \times (n-3) \times \cdots \times 1\] or \[n! = \begin{cases} 1 & \text{if $n$ is 0} \\ n \times (n-1)! & \text{otherwise}\end{cases}\]
The second can be expression computationally as:
def factorial(n):
if n == 0: # Our base case
return 1
else: # Our recursive case
return n * factorial(n - 1)Most recursive functions you encounter will have bodies that fit in the following general pattern:
if |||test for simple case|||:
|||Compute and return simple solution without recursion|||
else:
|||Divide the problem into one or more subproblems of the same form|||
|||Call this same function recursively to solve those subproblems|||
|||Return the solutions of the various subproblems|||Finding a recursive solution is thus commonly a matter of:

The plan with merge sort is thus to:
a1 and
a2a1 and
a2 recursivelya1 or
a2 on each cycleWe’ll follow this process all the way through on pen and paper now to see that it works!
def merge_sort(array):
if len(array) > 1: #base case check
mid = len(array) // 2
a1 = array[:mid]
a2 = array[mid:]
merge_sort(a1) #recursive calls
merge_sort(a2)
merge(array, a1, a2)
def merge(array, a1, a2):
n1 = len(a1)
n2 = len(a2)
i1 = 0 #current front indices
i2 = 0
for i in range(len(array)):
if (i1 < n1 and a1[i1] < a2[i2]) or i2 == n2:
array[i] = a1[i1]
i1 += 1
else:
array[i] = a2[i2]
i2 += 1
| \(N\) | \(N^2\) | \(N\log_2 N\) |
|---|---|---|
| 10 | 100 | 33 |
| 100 | 10,000 | 664 |
| 1,000 | 1,000,000 | 9,966 |
| 10,000 | 100,000,000 | 132,877 |
| 100,000 | 10,000,000,000 | 1,660,964 |
| 1,000,000 | 1,000,000,000,000 | 19,931,569 |
| Name | Big-O | Example |
|---|---|---|
| constant | \(\mathcal{O}(1)\) | Finding the first element of an array |
| logarithmic | \(\mathcal{O}(\log N)\) | Binary search in a sorted array |
| linear | \(\mathcal{O}(N)\) | Summing over an array, or linear search |
| \(N \log N\) | \(\mathcal{O}(N\log N)\) | Merge sort |
| quadratic | \(\mathcal{O}(N^2)\) | Selection sort |
| cubic | \(\mathcal{O}(N^3)\) | Obvious algorithms for matrix multiplication |
| exponential | \(\mathcal{O}(2^N)\) | Branch and try all possibilities |