Algorithms Midterm

0.0(0)
Studied by 0 people
call kaiCall Kai
learnLearn
examPractice Test
spaced repetitionSpaced Repetition
heart puzzleMatch
flashcardsFlashcards
GameKnowt Play
Card Sorting

1/35

encourage image

There's no tags or description

Looks like no tags are added yet.

Last updated 1:16 PM on 10/3/26
Name
Mastery
Learn
Test
Matching
Spaced
Call with Kai
Chat

No analytics yet

Send a link to your students to track their progress

36 Terms

1
New cards

Big-O (O)

Upper bound: "the algorithm takes AT MOST this long" (worst-case ceiling). Formal: f(n) = O(g(n)) if there are constants c > 0 and n0 such that f(n) ≤ c·g(n) for all n ≥ n0. Example: 3n + 5 = O(n) because 3n + 5 ≤ 4n once n ≥ 5.

2
New cards

Big Omega (Ω)

Lower bound: "the algorithm takes AT LEAST this long." Formal: f(n) = Ω(g(n)) if f(n) ≥ c·g(n) for all n ≥ n0. Example: 3n + 5 = Ω(n) because 3n + 5 ≥ 3n.

3
New cards

Big Theta (Θ)

Tight bound: the algorithm grows at EXACTLY this rate (both O and Ω). Formal: f(n) = Θ(g(n)) if c1·g(n) ≤ f(n) ≤ c2·g(n) for all n ≥ n0. Example: 3n + 5 = Θ(n).

4
New cards

How to calculate Big-O

1) Count the basic steps as a function of n. 2) Drop constants (5n → n). 3) Drop lower-order terms (n² + n → n²). 4) Keep the fastest-growing term. Example: 4n² + 10n + 7 → O(n²).

5
New cards

Growth order (slow to fast)

O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2^n) < O(n!)

6
New cards

Recurrence

An equation that defines a function in terms of itself on smaller inputs. In algorithms it describes the runtime of a recursive algorithm. Example (Mergesort): T(n) = 2T(n/2) + n means "solve two halves of size n/2, then do n work to combine." Base case: T(1) = constant.

7
New cards

Substitution Method

A way to solve a recurrence: 1) GUESS the answer (like T(n) = O(n log n)). 2) ASSUME it is true for smaller sizes (induction hypothesis). 3) PROVE it holds for n, picking a constant c that works. Example: T(n) = 2T(n/2) + n. Guess T(n) ≤ c·n·log n. Substitute: T(n) ≤ 2·c(n/2)log(n/2) + n = c·n·log n − c·n + n ≤ c·n·log n when c ≥ 1. So T(n) = O(n log n).

8
New cards

Master Theorem

A shortcut for recurrences of the form T(n) = a·T(n/b) + f(n), where a ≥ 1 (number of subproblems), b > 1 (shrink factor), f(n) = work outside the recursion. Compare f(n) to n^(log_b a). Case 1: f(n) smaller → T(n) = Θ(n^(log_b a)). Case 2: f(n) equal → T(n) = Θ(n^(log_b a) · log n). Case 3: f(n) bigger (and regular) → T(n) = Θ(f(n)).

9
New cards

Master Theorem example

Mergesort: T(n) = 2T(n/2) + n. a = 2, b = 2, so n^(log_2 2) = n. f(n) = n equals n → Case 2 → T(n) = Θ(n log n). Another: T(n) = 4T(n/2) + n. n^(log_2 4) = n². f(n) = n is smaller → Case 1 → Θ(n²). Another: T(n) = T(n/2) + n. n^(log_2 1) = 1. f(n) = n is bigger → Case 3 → Θ(n).

10
New cards

Recursive Algorithm

An algorithm that solves a problem by calling itself on smaller versions of the same problem until it reaches a base case. Needs: 1) a base case (stops recursion), 2) a recursive case (smaller input). Runtime is found with a recurrence. Pseudocode: Factorial(n): if n ≤ 1 return 1; return n * Factorial(n−1). Recurrence: T(n) = T(n−1) + O(1) → O(n). Best/Avg/Worst: depends on the algorithm; solve its recurrence.

11
New cards

Mergesort: runtime

Best: O(n log n). Average: O(n log n). Worst: O(n log n). Extra space: O(n). Stable. Idea: split in half, sort each half, merge. Recurrence: T(n) = 2T(n/2) + n.

12
New cards

Mergesort: pseudocode

MergeSort(A, left, right):  if left < right:   mid = (left + right) / 2   MergeSort(A, left, mid)   MergeSort(A, mid+1, right)   Merge(A, left, mid, right) Merge: copy both halves; repeatedly take the smaller front item of the two halves into A until both are empty.

13
New cards

Quicksort: runtime

Best: O(n log n) (pivot splits evenly). Average: O(n log n). Worst: O(n²) (pivot is always smallest/largest, e.g., sorted input with bad pivot). Extra space: O(log n). Not stable. Recurrence: T(n) = T(k) + T(n−k−1) + n.

14
New cards

Quicksort: pseudocode

QuickSort(A, low, high):  if low < high:   p = Partition(A, low, high)   QuickSort(A, low, p−1)   QuickSort(A, p+1, high) Partition(A, low, high):  pivot = A[high]; i = low − 1  for j = low to high−1:   if A[j] ≤ pivot: i = i+1; swap A[i], A[j]  swap A[i+1], A[high]  return i+1

15
New cards

Insertion Sort: runtime

Best: O(n) (already sorted). Average: O(n²). Worst: O(n²) (reverse sorted). Extra space: O(1). Stable. Idea: like sorting a hand of cards; insert each new item into its place in the sorted part.

16
New cards

Insertion Sort: pseudocode

InsertionSort(A):  for i = 1 to n−1:   key = A[i]   j = i − 1   while j ≥ 0 and A[j] > key:    A[j+1] = A[j]    j = j − 1   A[j+1] = key

17
New cards

Counting Sort: runtime

Best: O(n + k). Average: O(n + k). Worst: O(n + k). (k = range of values, n = number of items.) Extra space: O(n + k). Stable. Not comparison-based. Works for integers in a small range. Idea: count how many times each value appears, then place items.

18
New cards

Counting Sort: pseudocode

CountingSort(A, k):  C = array of size k+1, all 0  for each x in A: C[x] = C[x] + 1  for i = 1 to k: C[i] = C[i] + C[i−1]  for j = n−1 down to 0:   B[C[A[j]] − 1] = A[j]   C[A[j]] = C[A[j]] − 1  return B

19
New cards

Radix Sort: runtime

Best: O(d(n + k)). Average: O(d(n + k)). Worst: O(d(n + k)). (d = number of digits, k = base, e.g., 10.) Extra space: O(n + k). Stable. Idea: sort by the least significant digit first, then the next digit, and so on, using a stable sort (like Counting Sort) for each digit.

20
New cards

Radix Sort: pseudocode

RadixSort(A, d):  for digit = 1 to d (starting at the ones place):   use a stable sort (Counting Sort) to sort A by that digit Example: 170, 45, 75, 90 → sort by ones → sort by tens → sort by hundreds → 45, 75, 90, 170.

21
New cards

Bucket Sort: runtime

Best: O(n + k). Average: O(n + k) (data spread evenly). Worst: O(n²) (everything lands in one bucket). Extra space: O(n + k). Idea: spread items into buckets by value range, sort each bucket, then join them.

22
New cards

Bucket Sort: pseudocode

BucketSort(A):  create n empty buckets  for each x in A:   put x into bucket[floor(n * x)] (for values in [0,1))  for each bucket: sort it (usually Insertion Sort)  concatenate all buckets in order

23
New cards

Binary Sort (Binary Insertion Sort): runtime

Best: O(n log n) comparisons (O(n) data moves if already sorted). Average: O(n²). Worst: O(n²) because shifting items still costs O(n) each. Uses binary search to find where each item goes. Extra space: O(1). Stable.

24
New cards

Binary Sort: pseudocode

BinaryInsertionSort(A):  for i = 1 to n−1:   key = A[i]   pos = BinarySearch(A, key, 0, i−1) (find insert spot)   shift A[pos..i−1] right by one   A[pos] = key

25
New cards

Binary Search (often called "binary sort")

Finds an item in a SORTED array by checking the middle and discarding half each time. Best: O(1) (middle item). Average: O(log n). Worst: O(log n). Recurrence: T(n) = T(n/2) + 1.

26
New cards

Heap

A binary tree stored in an array that is "complete" (filled left to right). Max-heap: every parent ≥ its children (max at root). Min-heap: every parent ≤ children (min at root). For index i: parent = (i−1)/2, left child = 2i+1, right child = 2i+2. Height = O(log n).

27
New cards

Heap: runtimes

Peek at max/min: O(1). Insert: Best O(1), Average O(1) (random data), Worst O(log n). Extract max/min: O(log n) in all cases. Build Heap from an array: O(n). Heapsort: Best/Avg/Worst O(n log n), space O(1), not stable.

28
New cards

Heap: pseudocode (Insert and Extract)

Insert(H, x): add x at the end of the array; BubbleUp(H, last index). ExtractMax(H): save H[0]; move the last item to the root; shrink heap by 1; BubbleDown(H, 0); return the saved item. BuildHeap(A): for i = n/2 − 1 down to 0: BubbleDown(A, i). HeapSort(A): BuildHeap(A); repeat: swap root with last item, shrink heap, BubbleDown(A, 0).

29
New cards

Bubble-Up (Sift-Up)

Heap operation: move a new item UP the tree, swapping with its parent while it is bigger than the parent (max-heap). Best: O(1) (already in place). Average: O(1). Worst: O(log n) (travels to the root).

30
New cards

Bubble-Down (Sift-Down)

Heap operation: move an item DOWN the tree, swapping with its LARGER child while a child is bigger (max-heap). Best: O(1) (already in place). Average: O(log n). Worst: O(log n) (travels to a leaf).

31
New cards

Bubble Sort (in case "Bubble-Up/Down Sort" means this)

Repeatedly step through the list, swapping adjacent items that are out of order, so big items "bubble" to the end. Best: O(n) (already sorted, with an early-exit flag). Average: O(n²). Worst: O(n²). Space: O(1). Stable.

32
New cards

Rules of Thumb for Big-O

Rules of thumb: one loop = O(n); nested loops = O(n²); halving the problem each step = O(log n); loop with a halving step inside = O(n log n).

33
New cards

Bubble Sort Pseudocode

Pseudocode: BubbleSort(A): for i = 0 to n−2: swapped = false; for j = 0 to n−2−i: if A[j] > A[j+1]: swap them; swapped = true; if not swapped: st

34
New cards

Bubble Down Pseudocode

BubbleDown(H, i): loop: l = 2i+1; r = 2i+2; largest = i; if l < size and H[l] > H[largest]: largest = l; if r < size and H[r] > H[largest]: largest = r; if largest == i: stop; swap H[i], H[largest]; i = largest.

35
New cards

Bubble Up Pseudocode

BubbleUp(H, i): while i > 0 and H[i] > H[parent(i)]: swap H[i], H[parent(i)]; i = parent(i).

36
New cards

Binary Sort Pseudocode

BinarySearch(A, x): low = 0; high = n−1; while low ≤ high: mid = (low+high)/2; if A[mid] == x return mid; else if A[mid] < x low = mid+1; else high = mid−1; return not found.