Lessons in this course (10)

1. Big-O notation — time and space complexity

Basic★ Must knowLesson 1 of 10

Big-O describes how the running time (or memory) grows as the input size n grows, ignoring constants.

Big-ONameExamplen = 1,000,000 → roughly
O(1)ConstantArray index, dictionary lookup1 step
O(log n)LogarithmicBinary search, B-tree index seek20 steps
O(n)LinearLoop over a list, table scan1,000,000
O(n log n)LinearithmicGood sorting (merge, heap, quick average)20,000,000
O(n²)QuadraticNested loops over the same data, bubble sort10¹² — too slow
O(2ⁿ)ExponentialAll subsets, naive Fibonacciimpossible
O(n!)FactorialAll permutationsimpossible
csharp
bool ContainsDuplicate_N2(int[] a)            // O(n²) time, O(1) space
{
    for (int i = 0; i < a.Length; i++)
        for (int j = i + 1; j < a.Length; j++)
            if (a[i] == a[j]) return true;
    return false;
}

bool ContainsDuplicate_N(int[] a)             // O(n) time, O(n) space — trade memory for speed
{
    var seen = new HashSet<int>();
    foreach (var x in a) if (!seen.Add(x)) return true;
    return false;
}

Rules: drop constants (O(2n) → O(n)); keep the dominant term (O(n² + n) → O(n²)); different inputs get different letters (O(a + b), O(a × b)); amortised O(1) means usually O(1), occasionally more (e.g. List<T>.Add when it must grow).

Best / average / worst case: quicksort is O(n log n) on average but O(n²) in the worst case; hash lookups are O(1) average, O(n) worst (all keys collide).