CIS 3490 — Design & Analysis of Algorithms

interactive studio · pick a tool and play

⚠ EXAM MONDAY 2:30 PM · WRONG FIRST LINE = ZERO MARKS · TARGET 38/50

Section A: no partial marks · Section B (15): asymptotic analysis · Section C (10): algorithm tracing · Section D (15): design

keyboard: 19 tools · t trace · d design · m mock · p plan · ? panic · esc home

💾 your Flashcards "known" set and Design Bank self-ratings persist across reloads

📊 your progress · estimated exam-readiness

🆕 RECENT UPDATES · click to expand · built while you were away
autonomous-mode iterations · 2026-05-31
🆕 11 NEW PROGRAMS
  • Bellman-Ford · neg weights + cycle detect
  • 🔢 Gaussian Elimination · partial pivoting
  • 🌲 Heapsort · bottom-up + sift-down
  • AVL Tree · all 4 rotation types
  • Quicksort · Hoare partition + recursion log
  • 📊 Presorting Walkthrough · 5 problems
  • Strassen's · 7-mult D&C
  • Horner's Rule + LCM↔GCD demo
  • Pascal's Triangle · 4 modes + DP
  • Sorted Matrix Search · O(n) corner walk
  • 🕸 DAG Path Counter · Addition Rule + lattice
📊 LINE COVERAGE TRACKER

Live per-line hit counts on every step-emitting animator (Sort, Search, Heapsort, Quicksort, Bellman-Ford, Gauss, Matrix Search). Each line gets ✓ when fired; "COVERAGE COMPLETE" appears when every executable line has been hit, including both branches of every IF. Closes the user's "every line must be hit" requirement.

🔍 BROWSE TOOLS
  • · Live text filter on tiles
  • · 10 paradigm category chips (Analyze, Sort, Graph, T&C, D&C, DP, Greedy, Combo, Practice)
  • · 📚 Coverage Map: syllabus-organized topic → program crosswalk (~59 links)
  • · Distinct tile colors on every program
🤖 PROFESSOR TWIN
  • · Per-page context for ALL 37 views
  • · Now injects what algorithm you're studying into every Twin query automatically
📋 ASSIGNMENTS HUB

A2 added (was missing). All 90 marks of practice covered: A1 (10×3=30) + A2 (6×5=30) + A3 (5×6=30). Each question has its own solution reveal + links to the matching interactive program.

📈 SYLLABUS COVERAGE

All 9 chapters covered: Ch1 asymptotics · Ch2 brute force · Ch3 decrease & conquer · Ch4 graphs · Ch5 D&C · Ch6 T&C (all 3 parts) · Ch7 trees · Ch8 DP · Ch9 greedy · plus combinatorics. Lecture PDFs read: T&C Ch6 ×3, Quicksort, D&C, Decrease summary, Pascal, perms/combs.

35 programs · 526 KB · 7 animators with line-coverage · 37 views with Twin context
🔍 FILTER PROGRAMS

Sort Visualizer Q14–Q19

animated insertion · selection · bubble · merge with comparison & swap counters

comparisons0
swaps / shifts0
time elapsed0 ms
complexity (n=24)
state

    

📊 Line Coverage — proof every algorithm line is hit

Counts every step the animation emits per pseudocode line (incl. both TRUE and FALSE branches of every IF). After a complete run, every executable line should have count ≥ 1.

How insertion sort works

Bounds Visualizer Q1–Q5

drag c₁ / c₂ / n₀ — see when O, Ω, Θ hold

limit f/g as n→∞
claim in principle
your constants witness it

Big-O Proof Workshop Q6

3-step proof builder · prove f(n) ∈ O(g(n)) by definition

The 3-step skeleton (memorize):
1️⃣ "Need c > 0, n₀ ≥ 1 such that f(n) ≤ c·g(n) for all n ≥ n₀." — definition line
2️⃣ For each lower term: bound it by a multiple of g(n). (e.g. 5n ≤ 5n² when n ≥ 1; 100 ≤ n² when n ≥ 10)
3️⃣ Sum the coefficients → that's your c. Pick the strictest threshold → that's your n₀.

DFS / BFS Playground Q20–Q24

click empty space to add a node · click two nodes to add an edge · ▶ to traverse

visited order
stack / queue
tree edges0
back edges (cycle!)0
cross edges0

DFS pseudocode (highlights live during traversal)

DFS(G):
  for each v ∈ V: mark[v] ← 0   # unvisited
  count ← 0
  for each v ∈ V:
    if mark[v] = 0:
      DFS_VISIT(v)

DFS_VISIT(v):
  count ← count + 1
  mark[v] ← count
  for each unvisited w adj to v:
    DFS_VISIT(w)
# edge types: TREE (to unvisited) · BACK (to ancestor = CYCLE)
# complexity: Θ(|V| + |E|) on adj list

BFS pseudocode (highlights live during traversal)

BFS(G, s):
  initialize queue Q
  mark s as visited
  Q.enqueue(s)
  while Q ≠ ∅:
    u ← Q.dequeue()
    for each unvisited w adj to u:
      mark w as visited
      Q.enqueue(w)
# edge types: TREE (to unvisited) · CROSS (same/adj BFS level)
# gives shortest path (in # edges, unweighted)
# complexity: Θ(|V| + |E|) on adj list
trace state— click ▶ traverse to start —

⚠ Section C exam tip: when you trace a graph, write the pseudocode FIRST, then the iteration steps. Both are graded. Always label edges as Tree/Back/Cross.

Master Theorem Trainer Q13

T(n) = a·T(n/b) + f(n) — pick a, b, f and the case is identified

Three cases of the Master Theorem:
Let k = log_b(a). Then compare f(n) to n^k:
Case 1: f(n) = O(n^(k−ε)) → T(n) = Θ(n^k)
Case 2: f(n) = Θ(n^k) → T(n) = Θ(n^k · log n)
Case 3: f(n) = Ω(n^(k+ε)) + regularity → T(n) = Θ(f(n))
Examples: merge sort 2T(n/2)+n → k=1, f=n → Case 2 → Θ(n log n). Binary search T(n/2)+1 → k=0, f=1 → Case 2 → Θ(log n).

📝 Fill-in-the-Blank Quiz

Pick a recurrence, fill every blank from a dropdown, submit to grade. Exam-format step-by-step.

DP Table Walker Q45–Q48

non-adjacent max-sum · weighted activity selection · weighted interval scheduling (jobs) · fill cells one at a time

50-Question Flashcards Q1–Q50

every question from the cheatsheet · click card to flip · ← → to navigate

progress: 0 / 50
Q1 · Asymptotic notation
Loading…

Professor Twin DeepSeek

chat tutor primed on CIS 3490 — ask anything, work through problems

Yo. I'm primed on the CIS 3490 cheatsheet — Big-O proofs, recurrences, sorting analysis, graphs, DP, exam mechanics. Throw me a question or a problem and I'll walk you through it like you'd write it on paper. Try: "prove 4n²+7n+5 ∈ O(n²) step by step" or "explain merge sort recurrence".

backed by deepseek-chat · system prompt loaded with cheatsheet · stateless per turn

First-Move Drill EXAM CRITICAL

type the exact opening line for each problem · wrong = zero marks

⚠ THE RULE

Wrong first term = ZERO for entire question. No alternative methods accepted. No partial marks in Section A. Section B questions are worth 5 marks each — your first line alone is typically worth 2.

Drill until you can write each opening cold in under 10 seconds.

attempts (lifetime)0
correct0
accuracy
problems mastered (≥75% keywords once)0 / 34

MC Blitz · Section A 10 marks

10 MC + 5 SA · 60 seconds each · NO partial marks · from real midterm + 4 mock exams

question 1 / 30
timer60s
correct0
total0
accuracy
avg time

Trace Mode · Section C 10 marks

step through the exact exam arrays · marking-scheme table format · 2 trace questions × 5 marks

⚠ MARKING SCHEME REMINDER

Section C trace questions are graded on the table format above plus the derivation line below. Must use the technique asked (insertion = shift+insert, selection = find-min+swap, DFS = stack-based, BFS = queue-based). Alternative algorithms = 0 marks even if correct.

Always end with: C_worst(n) = Σ_{i=1}^{n-1} i = n(n−1)/2 ∈ Θ(n²) (insertion/selection) or Tree edges: ... | Back/Cross edges: ... (DFS/BFS).

Section D Design Bank 15 marks

12 real exam design problems · write pseudocode, reveal marking-scheme answer, self-rate

got it (5/5)0
partial (~3/5)0
missed (0/5)0
est. Section D marks if exam now

Study Plan · 48 hours target 38/50

official Master Plan schedule · each slot mapped to the right tool here

⏱ TIMELINE

Exam: Monday 2:30 PM · Now: Saturday/Sunday · Target: 38/50 (75%) — drop up to 12 marks and still pass.

Failure mode (per the Master Plan diagnosis): "conflates understanding with retrieval. The exam tests retrieval speed not depth." Every program here is timed/graded for retrieval.

📅 SATURDAY NIGHT (10 PM → 1 AM, then sleep)

10–11 PMBig-O / Ω / Θ definitions + limit method
11 PM–12 AMRecurrence setup from pseudocode
12–1 AMBackward substitution — easy cases first

SLEEP 6 hours minimum. Memory consolidates overnight.

📅 SUNDAY (7 AM → 10 PM)

7–9 AMBackward sub hard case: T(n)=2T(n/2)+n — merge sort, most-tested
9–10 AMSummation method — nested loops, S1/S2 formulas
10–11 AMSorting complexity derivation — insertion + selection worst case from Σ
11–12 PMDFS + BFS traces — label tree/back/cross edges
12–1 PMBREAK — eat, walk, NO SCREENmandatory
1–3 PM⚠ MOCK EXAM — full simulation. Timed. No notes. No Claude.
3–4 PMFix ONLY mock failures — circled questions only, write correct method once, move on
4–5 PMBrute force complexity — TSP O(n!), Knapsack O(2ⁿ), Assignment O(n³), Hull O(n³), ClosestPair Θ(n²)
5–6 PMJohnson-Trotter — find largest mobile → swap → reverse all larger. Trace n=3 fully.
6–7 PMSection A definitions blitz — 60 seconds per term, cold
7–8 PM★ FIRST-MOVE SETUPS for every problem type — THE MOST IMPORTANT SESSION
8 PM →REST — no studying. Walk. Eat. Wind down. Sleep 9 hours.structural, not optional

📅 MONDAY (6 AM → 2:30 PM exam)

6–8 AMCold recall ONLY — write every formula and first-move setup from memory, no notes
8 AM–12 PMPassive skim only — read your own Sunday notes, no new problems
12–2 PMTravel and rest — nothing neweat, arrive early
2:30 PM⚠ EXAM38/50

THE NON-NEGOTIABLE RULES

  • Every topic gets its time slot and then it ENDS. Physical timer. When it goes off, write DONE and move on.
  • One worked example → immediate cold attempt. No passive explanation.
  • Mock exam at 1 PM Sunday while FRESH — not after 8 hours of grinding.
  • After mock: fix only failures. Do not re-study what you got right.
  • Study ends 9 PM Sunday. Sleep 9 hours. Structural, not optional.
  • Monday is recall and rest only. No new learning after 8 AM.

Mock Exams · Full Review 4 × 50 marks

all 4 mocks from MockExam.pdf · 72 questions total · click 👁 per question to reveal

revealed: 0 / 18

After review: feed any wrong answers into if you missed the opening line, or if you missed pseudocode, or if you missed multiple-choice.

⚠ Mocks 2 (D&C), 3 (Asymptotic Deep Dive), and 4 (Full Coverage Hardest) are in your original MockExam.pdf. Print or open them on paper for additional cold simulations.

Prim's MST Section C/D

Mock 1 D22 graph · edge-by-edge growth · alphabetical tie-break · line-highlighted pseudocode

Iteration table

iterVTpicked edgewtotal

Pseudocode (live)


    
stateclick ▶ run
total weight

⚠ Section C/D exam reminder

When multiple candidate edges have the same min weight, the tie-break rule is: pick the edge whose NEW (non-tree) vertex comes first alphabetically. If still tied, pick the one whose tree vertex comes first alphabetically. Complexity: O(|V|²) array-based, O((V+E) log V) with a binary heap.

Dijkstra's Shortest Path single-source

same graph as Prim's · pick min unvisited · relax edges · live dist table

Distance table

vdist[v]prev[v]visited?

Pseudocode (live)


    
stateclick ▶ run

Notes

Dijkstra requires non-negative edge weights — for negative weights use Bellman-Ford. Complexity: O(V²) array-based, O((V+E) log V) with binary heap, O(E + V log V) with Fibonacci heap. Greedy paradigm: pick the closest unvisited each step (which is provably the final shortest distance).

Bellman-Ford Shortest Path handles negative weights

|V|-1 passes · relax every edge each pass · final pass detects negative cycles · DP paradigm

Distance table (per iteration)

vdist[v]prev[v]
pass 0 /

Pseudocode (live)


    
stateclick ▶ run

📊 Line Coverage — proof every BellmanFord line is hit

Tracks step-emit count per pseudocode line. After a complete run, all executable lines should be hit (the negative-cycle branch only fires when the chosen graph has one).

Why Bellman-Ford over Dijkstra?

Dijkstra fails with negative weights — its greedy choice (lock-in nearest unvisited) can finalize a vertex before a longer-then-cheaper-via-negative path is found. Bellman-Ford does NOT commit to any vertex; it simply relaxes every edge |V|-1 times. After |V|-1 passes, every shortest path of ≤ |V|-1 edges has stabilized. A |V|-th pass that still relaxes ANY edge ⇒ negative cycle exists.

Complexity: Θ(V·E). Slower than Dijkstra's O(E + V log V), but more general. Paradigm: Dynamic Programming — dist[v] is built up from shorter sub-paths.

Gaussian Elimination Transform & Conquer

solve Ax = b via row operations · forward eliminate → back-substitute · Θ(n³)

Augmented matrix [A | b]

edit a cell to switch to custom system · pink row = pivot · gold row = target

Pseudocode (live)


    

Step narration

click ▶ run

Solution (back-substitution)

📊 Line Coverage — BetterForwardElimination + Back-Substitution

Tracks step-emit count per pseudocode line. Pivot-search lines (3-7) fire only when partial pivoting is enabled.

Why is it Θ(n³)?

Three nested loops: outer i (1..n-1), middle j (i+1..n), inner k (i..n+1). Total mults ≈ Σᵢ₌₁ⁿ⁻¹ (n-i)(n-i+1) ≈ Σ p² ≈ n³/3. Doubling n → 8× runtime.

Partial pivoting swaps in the row with the largest |A[j,i]| as the pivot before eliminating. Why? In floating-point, dividing by a tiny pivot (e.g. 0.00001) creates a huge multiplier that swamps precision in other rows. Pivoting keeps the multiplier ≤ 1, preserving numerical stability. It also handles A[i,i]=0 (basic algorithm crashes).

Paradigm: Transform & Conquer / Instance Simplification — transform a general system into upper-triangular (a simpler instance), then solve by back-substitution.

Heapsort + Bottom-Up Heap Transform & Conquer · Representation Change

stage 1: bottom-up heapify Θ(n) · stage 2: extract-max + sift-down (n−1)× · total Θ(n log n) · in-place

Heap (tree view) · grey = sorted-out

phase: init · heap size:

Pseudocode (live)


    

Array (1-indexed) · green = sorted region

stepclick ▶ run

📊 Line Coverage — HeapBottomUp + SiftDown + Heapsort wrapper

Tracks step-emit count per pseudocode line. Both child-comparison branches of SiftDown should fire (left bigger vs right bigger).

Why is heap construction Θ(n) but heapsort Θ(n log n)?

Bottom-Up Heap Construction: A node at height h sifts down at most h levels. Most nodes are near the bottom (height 0/1), so cost = Σₕ h·(nodes at h) ≈ 2n ⇒ Θ(n). (Top-down insert-one-at-a-time costs Θ(n log n) — strictly worse.)

Heapsort: Stage 1 = Θ(n) construction; Stage 2 = n−1 extractions × O(log n) sift-down each = Θ(n log n). Overall Θ(n log n). In-place: the "deleted" max goes into the freed slot at the back, so the same array becomes the sorted output. Not stable — sift-down can reorder equal keys.

Mapping (1-indexed): root = H[1] · parent(i) = ⌊i/2⌋ · left(i) = 2i · right(i) = 2i+1. Last parent = ⌊n/2⌋. Leaves at indices ⌊n/2⌋+1..n already satisfy parental dominance (no children).

Paradigm: Transform & Conquer / Representation Change — re-represent the array as a max-heap, then exploit the dominance property to extract sorted elements.

AVL Tree Builder Transform & Conquer · Rotations

insert keys · live balance factors · auto-rotate on |BF|=2 · all 4 rotation types covered

Tree (BF labeled on each node)

inserted so far:

Rotation log


    
stepclick ▶ run preset

4 Rotation Types

L-Rot (Single Left)
path: R-R (right child of right child)
BF=−2, BF(right child)=−1
A→B→C ⇒ B as new root, A=B.left, C=B.right
R-Rot (Single Right)
path: L-L (left child of left child)
BF=+2, BF(left child)=+1
C←B←A ⇒ B as new root, A=B.left, C=B.right
LR-Rot (Double Left-Right)
path: L-R (zig-zag)
BF=+2, BF(left child)=−1
L-Rot at left child, then R-Rot at root
RL-Rot (Double Right-Left)
path: R-L (zig-zag)
BF=−2, BF(right child)=+1
R-Rot at right child, then L-Rot at root

BF formula: BF(node) = height(left) − height(right). AVL invariant: BF ∈ {−1, 0, +1} for every node. Height bound: h < 1.4405 log₂(n+2) − 1.3277. Search/Insert/Delete: Θ(log n) worst case.

Quicksort + Hoare Partition D&C · in-place

pivot = A[l] · scan i→ from left, ←j from right · swap on cross · recurse

Array · pink=pivot · gold=i · purple=j · green=sorted position locked

Recursion tree (subarrays)


    

Partition pseudocode (live)


    
stepclick ▶ run

📊 Line Coverage — proof every Partition/Quicksort line is hit

Tracks step-emit count per pseudocode line. Both TRUE and FALSE branches of every IF should fire across a complete sort.

Why partition is the soul of Quicksort

Hoare partition uses two scanning indices that walk toward each other. Index i scans left-to-right past anything strictly less than the pivot. Index j scans right-to-left past anything strictly greater than the pivot. Both stop at equality — this is critical for duplicates (otherwise an all-equal array splits 0 / n-1 and we get Θ(n²)). When i < j we swap A[i] ↔ A[j] and advance both. When i ≥ j we swap pivot ↔ A[j] to place pivot in its final position; j is returned as the split.

Recurrence: T(n) = T(k) + T(n−k−1) + Θ(n) where k = elements smaller than pivot. Best: k = n/2 each level ⇒ T(n)=2T(n/2)+n ⇒ Θ(n log n). Worst: k = 0 or n−1 (sorted, pivot=first ⇒ smallest each time) ⇒ T(n)=T(n−1)+n ⇒ Θ(n²). Average: ≈ 1.39·n log₂n — only ~39% slower than the theoretical optimum.

Quicksort is in-place (no auxiliary array like mergesort) but not stable (swaps can reorder equal keys). Median-of-three pivoting + Randomization push the worst case toward improbable.

Paradigm: Divide & Conquer — but unusual because all the work happens in the divide step (partitioning), none in the combine step (subarrays are already in their final relative regions).

Presorting Walkthrough Transform & Conquer · Instance Simplification

brute force vs presort: 5 classic problems · same input, see the speedup

Element Uniqueness

Brute Force · Θ(n²)


      
comparisons:
result:

Presort · Θ(n log n)


      
operations:
result:
sorted form:

The Big Lesson

Presorting trades the up-front cost of an O(n log n) sort for the dramatic simplification of the post-sort problem. Worth it when the post-sort algorithm is linear (so total is dominated by the sort) and you'd otherwise pay quadratic. Not worth it for a single sequential search (n log n + log n > n).

Searching m times on the same data: m·n (sequential) vs n log n + m log n (sort+binary). Crossover at m ≈ log n.

Paradigm: Transform & Conquer · Instance Simplification — transform an arbitrary array into a sorted one (simpler instance), then solve.

Strassen's Matrix Multiplication D&C · Θ(n^log₂7)

brute force Θ(n³) vs Strassen Θ(n^2.807) · live 2×2 trace with all 7 M-products

Matrix A (2×2)

Matrix B (2×2)

Preset

Brute Force · Θ(n³) · 8 mults


    

Strassen · Θ(n^log₂7) ≈ Θ(n^2.807) · 7 mults


    

Result C = A × B (both methods must agree)

Why does saving 1 multiplication matter so much?

For 2×2 the difference is trivial (7 vs 8 mults). But Strassen recurses: when n>2, each of the 7 sub-products is itself an (n/2)×(n/2) matrix multiplication done via Strassen. The recurrence is M(n) = 7M(n/2). By the Master Theorem (a=7, b=2, f(n)=Θ(n²)): a > b^d (7 > 4) ⇒ T(n) ∈ Θ(n^log_b a) = Θ(n^log₂7) ≈ Θ(n^2.807). Better than Θ(n³) by a polynomial factor.

The 7 magic products: M1 = (A00+A11)(B00+B11), M2 = (A10+A11)·B00, M3 = A00·(B01−B11), M4 = A11·(B10−B00), M5 = (A00+A01)·B11, M6 = (A10−A00)(B00+B01), M7 = (A01−A11)(B10+B11). Then: C00 = M1+M4−M5+M7, C01 = M3+M5, C10 = M2+M4, C11 = M1+M3−M2+M6. 7 multiplications + 18 additions.

Trade-off: Strassen uses 18 additions vs brute-force's 4 additions per 2×2. Constant overhead means Strassen only wins for large n (crossover ≈ 100 in practice). The naive D&C split (8 sub-products) gives the same Θ(n³) — Strassen's insight was that the algebraic identity reduces 8 to 7.

Paradigm: Divide & Conquer with algebraic refinement. Faster algorithms exist (Coppersmith-Winograd O(n^2.376), more recent ~O(n^2.371)), but huge hidden constants make them impractical.

Horner's Rule + Problem Reduction T&C · Representation Change

brute force Θ(n²) vs Horner Θ(n) · nested multiplications · plus LCM↔GCD reduction

Polynomial

Brute Force · Θ(n²)


      
multiplications: · additions:

Horner's Rule · Θ(n)


      
multiplications: · additions:

Result p(x)

Why Horner's Rule works

The insight: Brute force computes each x^i from scratch (no shared work). Horner factors the polynomial into nested form:

p(x) = (...((aₙ·x + aₙ₋₁)·x + aₙ₋₂)·x + ... + a₁)·x + a₀

Each iteration does one multiplication and one addition. n iterations total ⇒ n mults, n adds, total Θ(n). Brute force does (n+1)(n+2)/2 ∈ Θ(n²) mults due to recomputing powers. Horner is provably optimal for polynomial evaluation without preprocessing.

Paradigm: Transform & Conquer · Representation Change — re-express the polynomial in nested form to eliminate redundant work.

🔁 Bonus: LCM via GCD (Problem Reduction Demo)

Classic problem reduction: lcm(m,n) reduces to gcd(m,n) via the identity lcm(m,n) = m·n / gcd(m,n). GCD via Euclid is O(log n), so LCM also runs in O(log n). Old way: prime factorization (expensive).


  

Pascal's Triangle + Binomial DP DP · Combinatorics

click any cell · C(n,r) via formula, recurrence, and Pascal · (x+y)^n expansion

9

Selected: C(5, 2) = 10


    

Binomial expansion (x+y)^5


    

DP Recurrence (Binomial via Pascal's Identity)

function Binomial(n, r):                 // Θ(n·r) time, Θ(n·r) space
  if r == 0 or r == n: return 1            // base case
  return Binomial(n-1, r-1) + Binomial(n-1, r)

Bottom-up DP fills the triangle row-by-row, each cell = sum of two cells above.
This is the classic dynamic programming example — direct recursion repeats work
exponentially; memoization/DP reduces it to Θ(n·r) ⇐ store all C(n,r) for n' ≤ n.

4 Key Identities (all visible in the triangle)

1. Pascal's Identity: C(n+1, k) = C(n, k−1) + C(n, k). Every cell = sum of two cells above. This is the recurrence.
2. Symmetry: C(n, r) = C(n, n−r). Every row mirrors around its center. (Try "symmetry" mode above.)
3. Row sum: Σⱼ C(n, j) = 2ⁿ — total number of subsets of an n-set. (Try "row sum" mode.)
4. Hockey stick: Σⱼ₌ᵣⁿ C(j, r) = C(n+1, r+1) — diagonal sums. (Try "diagonal" mode.)
Plus Vandermonde: C(m+n, r) = Σ C(m, r−k)·C(n, k), and the binomial theorem (x+y)ⁿ = Σ C(n,j)·xⁿ⁻ʲyʲ — shown live in the right panel above.

Sorted Matrix Search Variable Decrease-and-Conquer · O(n)

rows + columns sorted · start top-right · K<curr → left, K>curr → down · each step kills a row or column

Matrix · pink = current cell · green = found · grey = eliminated

Pseudocode (live)


    

Step narration


      
comparisons: 0

📊 Line Coverage — SortedMatrixSearch

Tracks step-emit count per pseudocode line. Lines 5/7 (move-left vs move-down) both fire when the key isn't trivially at the corner.

Why O(n) and not O(n²) or O(log n)?

O(n²) brute force scans every cell. O(log n) per row using binary search × n rows = O(n log n). But the corner trick beats both: starting at the top-right corner exploits the sortedness of BOTH dimensions simultaneously. Each comparison decides "eliminate this whole row" or "eliminate this whole column" — never both. After at most n + n = 2n steps either we find K or we walk off the grid ⇒ O(n).

Variable decrease-and-conquer: the "decrease" is not a fixed n−1 or n/2 — it adapts per comparison (sometimes a row drops, sometimes a column drops). Bottom-left also works (mirror direction). Top-left and bottom-right do NOT — at those corners both moves go the same way and the algorithm fails.

Other "Variable Decrease" exam algorithms: Euclid's GCD (gcd(m,n) reduces to gcd(n, m mod n)), Interpolation Search (jump proportional to key value, expected O(log log n) on uniform data).

DAG Path Counter DP · Addition Rule

label S=1 · propagate up in topological order · each node N(v) = Σ N(u) for u→v · sum at F is the answer

Graph · S=green · F=red · current=pink · count above each node

Step narration


      
paths so far:

The Addition Rule

Process vertices in topological order. Label S = 1. For every vertex v after S, set N(v) = Σ N(u) over all u → v incoming edges. The value at F is the total path count. This works because every path to v ends with exactly one incoming edge from some u, and the paths through different u's are disjoint.

Complexity: Θ(V + E) — one pass through each vertex, summing its in-edges. Far better than the brute-force "enumerate every path" which is exponential.

Lattice paths connect to Pascal's triangle! The number of paths in an m×n grid from corner to corner (only right + up moves) is C(m+n, m). Try the lattice presets — the path count at the top-right corner matches Pascal's triangle entry. This is the classic "lattice paths = binomial coefficients" identity.

Paradigm: Dynamic Programming on a DAG. Stores intermediate path counts to avoid re-enumeration. Same technique powers shortest-path counting, viability checks, and many DP problems on DAGs.

Assignments Hub A1 + A3

every question from the CIS 3490 assignments · solution reveal · link to matching program

Each Q links to the program inside this studio that drills it. Click the ▶ button below the Q to see the marking-scheme solution. Practice the linked program first, then attempt the Q on paper, then reveal.

Write & Grade DeepSeek

write the algorithm yourself · DeepSeek grades on rubric · iterative practice

DeepSeek grades on the rubric below the mode selector. After submission you'll get: marks awarded, what you got right, what you missed, and a targeted re-do hint. Use this for Section D (Algorithm Design — 15 marks).

Topological Sort DAG only · Section C

Mock 4 C19 DAG · both methods · live ordering · line-highlight pseudocode

Live ordering

Per-vertex state

vertexfinishstate

Pseudocode (live)


    
stateclick ▶ run

Both methods are Θ(V+E). DAG required — any cycle makes topological order impossible (DFS would find a back edge; Kahn would leave non-zero in-degrees stuck). Method 1 (DFS): output vertices in REVERSE order of when they finish. Method 2 (Kahn): repeatedly find vertices with in-degree 0, output, remove their outgoing edges.

Binary Trees & BST recursive

BST insertion · 4 traversals · live tree visualization · line-highlight pseudocode

Visit order

Pseudocode (live)


    
stateclick ▶ run

A Binary Search Tree obeys: for every node, all left descendants are smaller and all right descendants are larger. Traversal complexities are all Θ(n). BST insert is Θ(log n) avg, Θ(n) worst (skewed). Self-balancing variants (AVL, red-black) guarantee Θ(log n). Use in-order traversal on a BST to read its values in sorted order.

Backward Substitution Trainer CRITICAL · Section B

step-by-step expansion of every standard recurrence · pattern recognition for the i-th step substitution

stepclick ▶ play

The standard backward-sub move (memorize): Expand T(n) by substituting the recurrence repeatedly. Look for the i-th step pattern: T(n) = T(n−i) + i·W for additive (or 2ⁱ·T(n−i) + W(2ⁱ−1) for doubling). Then set i so the base case appears: i = n − 1 for n→n−1 recurrences, i = log n for n→n/2 recurrences. Finally simplify with a Σ formula (Σi = n(n+1)/2, Σi² = n(n+1)(2n+1)/6, Σ2ⁱ = 2ⁿ−1).

Nested Loop Analyzer Section B · summation method

double / triple summation derivation · step-by-step algebra · matches sorting derivations

stepclick ▶ play

First-move setup (cheatsheet): C(n) = Σᵢ₌₀ⁿ⁻² Σⱼ₌ᵢ₊₁ⁿ⁻¹ 1
Σ formulas to remember: Σi = n(n+1)/2 · Σi² = n(n+1)(2n+1)/6 · Σi³ = [n(n+1)/2]²
Nested for j=i+1..n-1: inner count = (n-1) − (i+1) + 1 = n−1−i

Algorithm Paradigms Quiz 30 algorithms

identify the paradigm · learn what each algorithm IS doing

score: 0 / 0

The 6 paradigms (cheatsheet)

  • Brute Force — directly implement definition, no optimization (e.g. closest pair, TSP, knapsack)
  • Decrease & Conquer — ONE smaller instance: by constant (insertion sort), by factor (binary search), by variable (Euclid GCD)
  • Divide & Conquer — MULTIPLE independent subproblems, recurse, MERGE (merge sort, D&C find max)
  • Transform & Conquer — change representation, then solve (presort, Horner's, distribution counting)
  • Greedy — locally optimal at each step (SJF, Prim's, Dijkstra)
  • Dynamic Programming — optimal substructure + overlapping subproblems, build table (max non-adj, weighted activity)

🆘 Panic Card 2:25 PM Monday

every formula · every first-move · every edge case · one screen

DEFINITIONS

O(g):  ∃ c>0,n₀≥1: f(n) ≤ c·g(n) ∀n≥n₀
Ω(g):  ∃ c>0,n₀≥1: f(n) ≥ c·g(n) ∀n≥n₀
Θ(g):  O(g) AND Ω(g)
       c₁g ≤ f ≤ c₂g ∀n≥n₀

LIMIT TEST

lim T/g = 0   →  O, not Ω  (T slower)
lim T/g = c>0 →  Θ          (same)
lim T/g = ∞   →  Ω, not O  (T faster)

a^(log_b n) = n^(log_b a)
log(n!) = Θ(n log n)  [Stirling]

HIERARCHY (slow → fast)

1 ≺ log log n ≺ log n ≺ √n ≺ n
   ≺ n log n ≺ n² ≺ n³
   ≺ 2ⁿ ≺ 3ⁿ ≺ n! ≺ nⁿ

SUMMATIONS

Σi  = n(n+1)/2           Θ(n²)
Σi² = n(n+1)(2n+1)/6     Θ(n³)
Σi³ = [n(n+1)/2]²        Θ(n⁴)
Σaⁱ = (a^(n+1)-1)/(a-1)  Θ(aⁿ)
Σ√i ≈ (2/3)n^(3/2)       Θ(n^1.5)

RECURRENCES (memorize)

T(n-1)+1     → n              Θ(n)
T(n-1)+n     → n(n+1)/2       Θ(n²)
2T(n-1)+1    → 2ⁿ-1           Θ(2ⁿ)
T(n/2)+1     → log₂n          Θ(log n)
T(n/2)+n     → ~2n            Θ(n)
T(n/2)+log n → (log n)²/2     Θ(log²n)
2T(n/2)+1    → 2n-1           Θ(n)
2T(n/2)+n    → n log₂n        Θ(n log n)
2T(n-2)+1    → 2^(n/2)        Θ(2^(n/2))
3T(n/3)+n    → n log n        Θ(n log n)
4T(n/2)+n²   → n² log n       M.Case 2

MASTER THEOREM

T(n) = a·T(n/b) + f(n)
k = n^(log_b a)

Case 1: f = O(k^(1-ε))    → Θ(k)
Case 2: f = Θ(k)          → Θ(k log n)
Case 3: f = Ω(k^(1+ε))+reg → Θ(f)

Merge sort: 2T(n/2)+n
  → k=n, f=n → Case 2 → Θ(n log n)

SORTING

Insertion: best Θ(n), worst Θ(n²)
  C_worst = n(n-1)/2. STABLE. ONLINE.
  swaps = # inversions

Selection: Θ(n²) ALWAYS
  Exactly n-1 swaps. NOT stable.
  Best when writes expensive.

Bubble: best Θ(n) w/ flag, worst Θ(n²)
  Stable.

Merge: Θ(n log n) ALWAYS
  T=2T(n/2)+n → Case 2. Stable.
  Θ(n) extra space.

GRAPHS

DFS: stack/recursion. Tree+BACK edges.
     Back edge → CYCLE detected.
     Θ(V+E) on adj list.

BFS: queue. Tree+CROSS edges.
     Shortest path (unweighted).
     Θ(V+E) on adj list.

Topo sort: DAG only. Θ(V+E).
  Method 1: DFS, reverse finish order.
  Method 2: remove in-degree-0 vertices.

Prim's MST: Θ(V²) array, Θ((V+E)logV) heap.
  V-1 edges. Tie: alphabetical NEW vertex.

BRUTE FORCE

Closest Pair: C(n,2). dx²+dy². Θ(n²).
  D&C: O(n log n).

Convex Hull: a=yⱼ-yᵢ, b=xᵢ-xⱼ,
  c=xᵢyⱼ-yᵢxⱼ. val=axₖ+byₖ-c.
  Hull iff same sign for ALL k. O(n³).

TSP: (n-1)!/2 tours. O(n!). NP-Hard.
Knapsack: 2ⁿ subsets. NP-Hard.
Assignment: O(n³) Hungarian. NOT NP-Hard!
String match: O(nm). Avg Θ(n).

FIRST-MOVE SETUPS

Prove O: "Need c>0, n₀≥1 s.t.
  f(n) ≤ c·g(n) for all n ≥ n₀."

Limits: "lim(n→∞) f(n)/g(n)."

Backward sub: "T(n)=T(n-1)+W
  = T(n-i)+iW. At i=n: T(0)+nW."

Master: "a=__,b=__,f=__.
  k=n^(log_b a)=__. Compare→Case __."

Insertion worst: "C(n)=Σᵢ₌₁ⁿ⁻¹ i = n(n-1)/2"

DP non-adj: "M(0)=0, M(1)=A[1].
  M(i)=max(M(i-1), A[i]+M(i-2))."

YOU NEED 38/50.

Section A (10) target: 7-8 · Section B (15) target: 10-12 · Section C (10) target: 7-8 · Section D (15) target: 8-10

First line correct = partial marks. Use this. You have the time. Execute the plan.

🤖 Professor Twin

click to open · ask about this page