Merging Types

Jed Rembold

December 3, 2025

Announcements

  • Infinite Adventure due tonight!
    • 6 of you still haven’t even accepted the assignment?
  • Exam 2 corrections due end of Friday!
    • Only 2 have accepted so far?
  • Optional/Make-up Section meetings today or tomorrow!
  • Review materials are out!
  • Advent of Code has started!
    • Can join my leaderboard using code 3198345-61d515c2
    • I’ll give you some class participation points for each day’s puzzles that you complete
  • Polling: polling.jedrembold.prof

Review Question

Computing an element of the Fibonacci sequence is a classic recursive problem that can be solved by:

def fibonacci(n):
    if n <= 1:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)

How many times (including the first) does the function get called when calling fibonacci(5)?

  1. 5
  2. 6
  3. 15
  4. 25

Merge Sort

The Merge Sort Plan

The plan with merge sort is thus to:

  1. Divide the array into two halves: a1 and a2
  2. Sort each of a1 and a2 recursively, with a base case when the list has a single element
  3. Merge elements into the original array by choosing the smallest element from a1 or a2 on each cycle

We’ll follow this process all the way through on pen and paper now to see that it works!

Merge Sort Code Implementation

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

Merge Sort Complexity

image/svg+xml Sorting 8 items requires Two sorts of 4 items which requires Four sorts of 2 items which requires Eight sorts of 1 item
 
  • The work done at each level (all the work done by calls at that level) is proportional to the size of the array
  • Running time is therefore proportional to \(N\) times the number of levels

So how many levels?

  • Same division-by-two situation we had with Binary Search!
    • Equal to the number of times you can divide the array in half until only a single element remaining
    • Number of steps \(k\) was given by: \[k = \log_2(N)\]
  • Total complexity of merge sort is thus \[\mathcal{O}(N \log_2(N))\]

Comparing

\(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
  • Based on this, the merge sort would be over 50,000x faster than selection sort for an array of 1 million values!

General Complexity

Standard Complexity Classes

  • Most tend to fall into one of a small number of complexity classes
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
  • In general, any problem whose complexity can not be expressed as a polynomial is considered intractable

P vs NP

image/svg+xml P NP Easy to solve Easy to verify ? = ?
 

Annotating Type

What are Type Annotations?

  • Python is a dynamically typed language: we can change around what type of object is assigned to different variables whenever we want

    • This is often convenient, but can get confusing as programs get more complex
    • It can be useful for us to specify what types of things we expect certain variables to contain
      • These are just guidelines! They don’t actually change how the code runs at all
  • We can indicate these types by using type hints or type annotations

    def greet(name: str) -> str:
        return f"Hello, {name}!")

Why use Type Hints?

Improve Readability
Your hints contain bits of documentation, that makes it easier to understand functions and methods at a glance
Early Error Detection
Many IDEs can use type hints to catch common errors before you would run your program
Better Autocompletion
Many IDEs can use type hints to give you better autocomplete suggestions

Variable Annotations

  • You can specify what type a variable should have by including the type after a colon when you declare the variable name

    user_name: str = "Jed"
    age: int = 40
    is_living: bool = True
  • If you have compound structures, you can indicate the contents:

    profs: list[str] = ['Jed', 'Calvin', 'Fred']
    prof_start: tuple[str, int] = ('Jed', 2015)
    profs_start: list[tuple[str, int]] = [
      ('Jed', 2015), ('Calvin', 2022)
    ]
    prof_dict: dict[str, int] = {'Jed': 2025}

Function Annotations

  • Even more than variable annotations, function annotations can be extremely useful to define input and output types

    def myfunc(x: int, y: float, z: bool = True) -> float:
        if z:
            return x * y
        else:
            return x / y
  • Hints come before any default values

  • Use the -> |||type||| syntax to specify what will be returned

Different Types

  • Sometimes, you do want to allow for situations where a variable might have multiple possible types

    • This is particularly true if you want a variable to potentially be None
  • You can used the | symbol to indicate multiple variable types:

    def index_finder(
      array: list[str], 
      target: str
    ) -> int | None:
      for i, elem in enumerate(array):
          if elem = target:
              return i

Evals!

Please fill out course evals!

  • You should have gotten an email a bit back with a link to fill out our course evaluations
  • Alternatively, you should see a Course Evaluations list in Canvas now for your class
  • Please take the time to fill these out, especially with recommendations!
    • Only 9 of you have done filled them out so far (that is all I can see at the moment)
  • I am teaching this course again in the Spring, and am always trying to implement new ideas that might better foster student learning and retention
// reveal.js plugins