Everything on the site.

Big-O notationAlgorithms · Count the steps in real loops, then compare n, n log n, n² and 2ⁿ on a live chart.RecursionAlgorithms · Watch frames push and pop on the call stack for factorial and Fibonacci.BFS vs DFSAlgorithms · A queue against a stack: draw a graph and see which order each search visits it in.Sorting algorithmsAlgorithms · Seven sorts on the same input, with comparison, swap and write counts side by side.Binary searchAlgorithms · Halve the range, probe the middle, repeat: with lo, mid and hi drawn on the array.Sets, relations and functionsDiscrete maths · Shade any set expression on a Venn diagram and test a relation for its properties.Proof by inductionDiscrete maths · Four worked proofs revealed one step at a time, and a broken one to diagnose.CombinatoricsDiscrete maths · An exact nPr and nCr calculator, and a Pascal’s triangle that shows its own addition rule.Boolean algebraDiscrete maths · The laws, De Morgan, and normal forms, with a truth-table generator built in.Finite-state machinesTheory · Build a DFA in a table, see it drawn, and run strings through it one symbol at a time.Domain theoryTheory · Why recursion needs least fixed points, and how CPOs, Scott continuity and powerdomains supply them.Truth table generatorTools · Expression in, truth table out: with DNF, CNF, a minimal form and LaTeX.Graph traversal visualiserTools · Draw a graph, then animate BFS, DFS and Dijkstra with the frontier shown.Recursion tree visualiserTools · Paste a recursive function or a recurrence and see its call tree and call count.Gradient descentML maths · Drag the starting point, set the learning rate, and watch it converge or blow up.Vectors and embeddingsML maths · Bend the plane with a 2×2 matrix and measure how close toy word vectors are.Softmax and cross-entropyML maths · Edit the logits and watch the probabilities, the loss and the gradient update live.AttentionML maths · Q, K and V for three tokens, a live score heatmap, and the weighted sum of values.Formatting a CS paper in LaTeXLaTeX · Page limits, \documentclass, front matter, theorem environments and the bibliography.Camera-ready checklistLaTeX · Fonts embedded, PDF/A, copyright form, source bundle, and why final versions get rejected.LaTeX templatesLaTeX · Where the official classes live, plus a minimal article template you can copy.AlgorithmsSection · Step-through visualisations of sorting, searching, recursion, graph traversal and Big-O growth, each with pseudocode that highlights the line being run.Discrete mathsSection · Sets, relations and functions, proof by induction, counting, and Boolean algebra, explained with worked examples and small interactive checkers.TheorySection · Finite-state machines, automata and the mathematical semantics of programming languages, explained from first principles.ML mathsSection · Gradient descent, vectors and embeddings, softmax and cross-entropy, and attention, each with a formula, a worked numeric example and a live version.ToolsSection · A truth-table generator with CNF, DNF and LaTeX output, a graph-traversal visualiser for BFS, DFS and Dijkstra, and a recursion-tree visualiser.LaTeXSection · How to format a CS conference or workshop paper in LaTeX, a camera-ready checklist, and a minimal template you can adapt.
Algorithms

Big-O notation, explained with growth curves

Big-O notation describes how the work an algorithm does grows as its input gets bigger. It deliberately ignores constant factors and small inputs, so you can compare algorithms without timing them on a particular machine.

Interactive: Growth-curve chart and a step counter for five loop shapesUpdated

Suppose one program takes 3 seconds on a list of 10,000 items and another takes 5. Which is better? You can’t tell yet. If the first program’s running time grows in proportion to the square of the input size and the second grows in proportion to the size, the second wins comfortably once the list reaches a million items, whatever their timings at 10,000. Big-O is the vocabulary for that kind of statement.

Count steps, not seconds

Seconds depend on the processor, the language, the compiler and what else the computer is doing. So instead we pick a basic step, something that takes a bounded amount of time such as a comparison, an addition or an array access, and count how many of them the algorithm performs as a function of the input size nn.

For loops this is mostly a matter of multiplying. A loop that runs nn times with a constant amount of work inside costs about nn steps. A loop inside a loop, both running nn times, costs n⋅n=n2n \cdot n = n^2. A loop that halves its counter each time runs only about log⁡2n\log_2 n times, because that is how many halvings it takes to get from nn down to 1.

The stepper below runs five common loop shapes. Every square is one execution of the innermost line. Step through a small case, then drag nn up and watch how differently the totals grow.

Count the stepsEach square is one run of the innermost line. Change n and compare the total with the formula.

Pseudocode

    Variables

    Total

    0Steps so far
    0Formula

    Notice the triangle loop: its inner loop runs 1,2,…,n1, 2, \dots, n times, for a total of n(n+1)/2n(n+1)/2. That is roughly half of the full nested loop, but it still grows like n2n^2. Doubling nn roughly quadruples the work in both. That shared growth rate is what Big-O captures.

    The definitions

    Let f(n)f(n) be the number of steps an algorithm takes and g(n)g(n) a simple comparison function such as n2n^2.

    Big-O, Big-Omega and Big-Theta

    f(n)=O(g(n))f(n) = O(g(n)) means there are constants c>0c > 0 and n0n_0 such that f(n)≤c g(n)f(n) \le c\,g(n) for every n≥n0n \ge n_0. It is an upper bound: eventually, ff grows no faster than a constant multiple of gg.

    f(n)=Ω(g(n))f(n) = \Omega(g(n)) means f(n)≥c g(n)f(n) \ge c\,g(n) for all n≥n0n \ge n_0, for some c>0c > 0. It is a lower bound.

    f(n)=Θ(g(n))f(n) = \Theta(g(n)) means both hold: ff grows at exactly the rate of gg, up to constant factors.

    The “=” sign is a long-standing abuse of notation: O(g(n))O(g(n)) is really a set of functions, and f(n)=O(g(n))f(n) = O(g(n)) means ff belongs to it. Donald Knuth’s 1976 note in SIGACT News is the reason computer scientists use Ω and Θ the way they do today.

    Worked example: 3n2+5n+2=Θ(n2)3n^2 + 5n + 2 = \Theta(n^2)

    Upper bound. We want 3n2+5n+2≤c n23n^2 + 5n + 2 \le c\,n^2. Try c=4c = 4: the inequality becomes 5n+2≤n25n + 2 \le n^2. At n=5n = 5 the left side is 27 and the right is 25, so it fails; at n=6n = 6 it is 32≤3632 \le 36, and from there n2n^2 pulls away. So c=4c = 4, n0=6n_0 = 6 works, and 3n2+5n+2=O(n2)3n^2 + 5n + 2 = O(n^2).

    Lower bound. For every n≥1n \ge 1, 3n2+5n+2≥3n23n^2 + 5n + 2 \ge 3n^2, so c=3c = 3, n0=1n_0 = 1 shows it is Ω(n2)\Omega(n^2).

    Both bounds hold, so it is Θ(n2)\Theta(n^2). The 5n+25n + 2 and the factor 3 are absorbed by the constants.

    A quicker test, when the limit exists: if lim⁡n→∞f(n)/g(n)\lim_{n\to\infty} f(n)/g(n) is a finite positive number then f=Θ(g)f = \Theta(g); if it is 0 then f=O(g)f = O(g) but not Θ(g)\Theta(g). Here (3n2+5n+2)/n2→3(3n^2 + 5n + 2)/n^2 \to 3.

    The usual growth classes

    ClassNameTypical example
    O(1)O(1)constantReading A[i]; pushing onto a stack
    O(log⁡n)O(\log n)logarithmicBinary search on a sorted array
    O(n)O(n)linearFinding the largest value in an unsorted list
    O(nlog⁡n)O(n \log n)linearithmicMerge sort and heapsort; any comparison sort’s best possible worst case
    O(n2)O(n^2)quadraticInsertion sort in the worst case; checking every pair
    O(n3)O(n^3)cubicMultiplying two n×nn \times n matrices the schoolbook way
    O(2n)O(2^n)exponentialTrying every subset of nn items
    O(n!)O(n!)factorialTrying every ordering, as in brute-force travelling salesman

    The chart puts them side by side. With a linear vertical axis the exponential and factorial curves leave the top of the chart almost at once; switch to a logarithmic axis to keep them in view. The table on the right turns step counts into time at a billion steps per second, which is generous for most real code.

    Growth-rate chart

    Show
    f(n)StepsAt 10⁹ steps/s

    At n=1000n = 1000, an nlog⁡2nn \log_2 n algorithm needs about ten thousand steps, a quadratic one a million, and a cubic one a billion: microseconds, a millisecond and a second. An exponential algorithm needs about 1030110^{301} steps, which no computer will ever finish. That gap is why improving the growth rate matters far more than shaving constants.

    Rules of thumb

    • Drop constants and lower-order terms. 7n3+100n2+9=Θ(n3)7n^3 + 100n^2 + 9 = \Theta(n^3).
    • Sequential parts add; nested parts multiply. A linear pass followed by a quadratic one is O(n+n2)=O(n2)O(n + n^2) = O(n^2). A linear loop around a logarithmic one is O(nlog⁡n)O(n \log n).
    • The base of a logarithm doesn’t matter. log⁡an=log⁡bn/log⁡ba\log_a n = \log_b n / \log_b a, a constant multiple, so we just write O(log⁡n)O(\log n).
    • Recursive algorithms give recurrences. Merge sort satisfies T(n)=2T(n/2)+nT(n) = 2T(n/2) + n, which solves to Θ(nlog⁡n)\Theta(n \log n). The recursion tree visualiser solves recurrences of this shape and shows why.

    Common misunderstandings

    Big-O is not “the worst case”

    Best, average and worst case are about which inputs you consider. O, Ω and Θ are about how you bound a function. They are independent: insertion sort’s best case (already sorted input) is Θ(n)\Theta(n) and its worst case (reversed input) is Θ(n2)\Theta(n^2). You can see both in the sorting visualiser by choosing “Reversed” and then sorting the result again.

    An upper bound can be loose

    Technically linear search is O(n2)O(n^{2}), since anything bounded by nn is also bounded by n2n^2. That statement is true but not useful. When people say “O” informally they usually mean the tightest bound they know, which is really Θ.

    Constants still matter in practice

    Asymptotic notation says nothing about small inputs. For short arrays, insertion sort often beats merge sort because its inner loop is so simple, which is why library sorting routines switch to insertion sort for small pieces. Use Big-O to rule out approaches that cannot scale, then measure.

    Averages over a sequence of operations

    Appending to a dynamic array occasionally costs O(n)O(n), when the array is full and must be copied into a bigger one. If the capacity doubles each time, the total cost of nn appends is still O(n)O(n), so each append is O(1)O(1) amortised. Amortised analysis gives guarantees for sequences of operations rather than single ones.

    References

    1. D. E. Knuth, “Big Omicron and big Omega and big Theta”, ACM SIGACT News 8(2), 1976. doi:10.1145/1008328.1008329
    2. D. D. Sleator and R. E. Tarjan, “Amortized efficiency of list update and paging rules”, Communications of the ACM 28(2), 1985. doi:10.1145/2786.2793
    3. T. H. Cormen, C. E. Leiserson, R. L. Rivest and C. Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022. Chapter 3 covers asymptotic notation.
    4. R. L. Graham, D. E. Knuth and O. Patashnik, Concrete Mathematics, 2nd ed., Addison-Wesley, 1994. Chapter 9 treats asymptotics in depth.