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.
| Shape | Function | 10 items | 100 items | 1,000 items |
|---|---|---|---|---|
| O(1) | read one item | 1 | 1 | 1 |
| O(log n) | halvings | 3 | 6 | 9 |
| O(n) | onePass | 10 | 100 | 1,000 |
| O(n) | twoPasses | 20 | 200 | 2,000 |
| O(n²) | everyPair | 100 | 10,000 | 1,000,000 |
halvings(1,000,000) returns 19.
Pseudocode
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 stepsThe 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;
}
}def halvings(n):
steps = 0
while n > 1:
n = n // 2
steps = steps + 1
return steps
def one_pass(nums):
steps = 0
for x in nums:
steps = steps + 1
return steps
def every_pair(nums):
steps = 0
for x in nums:
for y in nums:
steps = steps + 1
return steps
def two_passes(nums):
steps = 0
for x in nums:
steps = steps + 1
for x in nums:
steps = steps + 1
return steps
# O(n * n) time, O(1) space
def contains_duplicate_brute(nums):
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] == nums[j]:
return True
return False
# O(n) time, O(n) space
def contains_duplicate(nums):
seen = set()
for x in nums:
if x in seen:
return True
seen.add(x)
return False#include <unordered_set>
#include <vector>
using namespace std;
long long halvings(long long n) {
long long steps = 0;
while (n > 1) {
n = n / 2;
steps = steps + 1;
}
return steps;
}
long long onePass(const vector<int>& nums) {
long long steps = 0;
for (int x : nums) {
steps = steps + 1;
}
return steps;
}
long long everyPair(const vector<int>& nums) {
long long steps = 0;
for (int x : nums) {
for (int y : nums) {
steps = steps + 1;
}
}
return steps;
}
long long twoPasses(const vector<int>& nums) {
long 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
bool containsDuplicateBrute(const vector<int>& nums) {
for (size_t i = 0; i < nums.size(); i++) {
for (size_t j = i + 1; j < nums.size(); j++) {
if (nums[i] == nums[j]) {
return true;
}
}
}
return false;
}
// O(n) time, O(n) space
bool containsDuplicate(const vector<int>& nums) {
unordered_set<int> seen;
for (int x : nums) {
if (seen.count(x)) {
return true;
}
seen.insert(x);
}
return false;
}function halvings(n) {
let steps = 0;
while (n > 1) {
n = Math.floor(n / 2);
steps = steps + 1;
}
return steps;
}
function onePass(nums) {
let steps = 0;
for (const x of nums) {
steps = steps + 1;
}
return steps;
}
function everyPair(nums) {
let steps = 0;
for (const x of nums) {
for (const y of nums) {
steps = steps + 1;
}
}
return steps;
}
function twoPasses(nums) {
let steps = 0;
for (const x of nums) {
steps = steps + 1;
}
for (const x of nums) {
steps = steps + 1;
}
return steps;
}
// O(n * n) time, O(1) space
function containsDuplicateBrute(nums) {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] === nums[j]) {
return true;
}
}
}
return false;
}
// O(n) time, O(n) space
function containsDuplicate(nums) {
const seen = new Set();
for (const x of nums) {
if (seen.has(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
| Function | Time | Extra space |
|---|---|---|
halvings | O(log n) | O(1) |
onePass, twoPasses | O(n) | O(1) |
everyPair | O(n²) | O(1) |
containsDuplicateBrute | O(n²) | O(1) |
containsDuplicate | O(n) on average | O(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.
Solve it with a loop inside a loop. Then in one pass with a hash set. Name the Big-O of each.
Write only the brute force. Work out its Big-O. Would it survive a huge input?






