02Foundations

Big-O: time and space

Count how the steps grow with the input: O(1), O(log n), O(n), O(n²).

Big-O tells you if your solution is fast enough before you run it. It ignores seconds and asks one question: when the input grows, how fast do the steps grow?

The idea

Your teacher has 1,000 answer sheets and wants yours. Flip through them one by one and, on a bad day, you look at all 1,000. If they are sorted by roll number, open the middle, drop the half that can't hold yours, and repeat: 9 cuts. Same job, very different work. Big-O is the name for that difference.

Read it from the code: one loop over the input is O(n); a loop inside a loop is O(n²); halving the input every step is O(log n). Space counts the same way: a few variables are O(1), a new array of n items is O(n).

The walk

Step counts as on the slides. The O(1) row is reading one item, such as nums[0]; the other rows were measured by running the functions below.

ShapeFunction10 items100 items1,000 items
O(1)read one item111
O(log n)halvings369
O(n)onePass101001,000
O(n)twoPasses202002,000
O(n²)everyPair10010,0001,000,000

halvings(1,000,000) returns 19.

Pseudocode

Pseudocode · any language
function onePass(nums):
    steps = 0
    for each x in nums:
        steps = steps + 1
    return steps          // n

function everyPair(nums):
    steps = 0
    for each x in nums:
        for each y in nums:
            steps = steps + 1
    return steps          // n * n

function halvings(n):
    steps = 0
    while n > 1:
        n = floor(n / 2)
        steps = steps + 1
    return steps

The trap: loops in a row don't multiply. Two loops, one after the other, over 1,000 items take 2,000 steps: still O(n). Only a loop inside a loop gives 1,000,000 steps, O(n²). The code below also has twoPasses, which shows this, and both ways to solve Contains Duplicate from the last slide.

Code

import java.util.HashSet;
import java.util.Set;

public class BigO {
    static long halvings(long n) {
        long steps = 0;
        while (n > 1) {
            n = n / 2;
            steps = steps + 1;
        }
        return steps;
    }

    static long onePass(int[] nums) {
        long steps = 0;
        for (int x : nums) {
            steps = steps + 1;
        }
        return steps;
    }

    static long everyPair(int[] nums) {
        long steps = 0;
        for (int x : nums) {
            for (int y : nums) {
                steps = steps + 1;
            }
        }
        return steps;
    }

    static long twoPasses(int[] nums) {
        long steps = 0;
        for (int x : nums) {
            steps = steps + 1;
        }
        for (int x : nums) {
            steps = steps + 1;
        }
        return steps;
    }

    // O(n * n) time, O(1) space
    static boolean containsDuplicateBrute(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[i] == nums[j]) {
                    return true;
                }
            }
        }
        return false;
    }

    // O(n) time, O(n) space
    static boolean containsDuplicate(int[] nums) {
        Set<Integer> seen = new HashSet<>();
        for (int x : nums) {
            if (seen.contains(x)) {
                return true;
            }
            seen.add(x);
        }
        return false;
    }
}

Math.floor matters in halvings: in JavaScript, / always gives a decimal, so 7 / 2 is 3.5, not 3.

Complexity

FunctionTimeExtra space
halvingsO(log n)O(1)
onePass, twoPassesO(n)O(1)
everyPairO(n²)O(1)
containsDuplicateBruteO(n²)O(1)
containsDuplicateO(n) on averageO(n)

How it was tested

All four languages produce the measured step counts in the table above. Every function was then run in all four languages on 3,007 inputs (3,000 random arrays of length 0 to 12, the 10-, 100- and 1,000-item arrays, an empty array and a 2,000-item array) and checked against the expected counts; the two Contains Duplicate versions were checked against each other and against a set-size test. All four languages agreed on every input.

Practice

Try these in order. Open the worked example first if you got stuck on the slides.