Lesson 4 of 30
You don't need to calculate Big O with math. You can recognize the four most common patterns — O(1), O(n), O(n^2), O(log n) — just by looking at the shape of the code.
13 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
The last lesson introduced the idea of Big O without the letters and symbols. This lesson gives you those labels, and — more importantly — teaches you to recognize them just by glancing at code, the way you'd recognize a stop sign by its shape before you consciously read the word "STOP."
O(1) means "the same amount of work no matter how big the input is." Grabbing the first item in a list is O(1) — it doesn't matter if the list has 5 items or 5 million, grabbing the first one takes one step either way.
O(n) means "the work grows in a straight line with the input." A single loop that checks every item once is O(n) — double the list, double the checks. This is the "read every name in the phone book" search from the last lesson.
O(n^2) means "the work grows by the square of the input" — usually because you're looping inside another loop, checking every item against every other item. Double the input, and the work roughly quadruples. This shows up a lot in beginner code without anyone intending it.
O(log n) means "the work barely grows, even as the input gets huge" — this is the "flip and narrow" phone-book search. Each step cuts the remaining work roughly in half.
The trick to recognizing these by eye: count the loops, and notice whether they're nested. One loop over the input, alone, is almost always O(n). A loop inside another loop, both touching the input, is almost always O(n^2). No loop at all, just direct access, is O(1). A loop that cuts the problem in half each time it repeats is O(log n).
// O(1): grabs one item directly, no loop — same speed at any input size.
function getFirst(arr) { return arr[0]; }
// O(n): one loop, touches every item once — work grows in a straight line.
function containsValue(arr, target) {
for (let i = 0; i < arr.length; i++) if (arr[i] === target) return true;
return false;
}
// O(n^2): a loop inside a loop, both over the input — work grows by the square.
function hasDuplicate(arr) {
for (let i = 0; i < arr.length; i++)
for (let j = 0; j < arr.length; j++)
if (i !== j && arr[i] === arr[j]) return true;
return false;
}
// O(log n): cuts the search space in half each step (array must be sorted).
function binarySearch(sortedArr, target) {
let low = 0, high = sortedArr.length - 1;
while (low <= high) {
const mid = Math.floor((low + high) / 2);
if (sortedArr[mid] === target) return mid;
if (sortedArr[mid] < target) low = mid + 1;
else high = mid - 1;
}
return -1;
}
.includes() or .indexOf(), loop internally even though you don't see a for written out. Using one inside your own loop can quietly create an O(n^2) pattern.These four shapes are the ones you'll spot over and over for the rest of this track and in real interviews. The next two lessons — arrays and strings — will point out exactly where O(1), O(n), and O(n^2) show up in the data structures you already use every day.