Big O notation describes how much more work an operation does as the data grows. It ignores the exact time, which depends on the machine, and keeps only the shape of the growth. n stands for the size of the data: the number of entries, items, or characters.
| Notation | Name | As the data grows, the work | Examples |
|---|---|---|---|
O(1) | Constant | Stays the same, whether there are 10 entries or 10 million. | map.get(key), array[i], array.push(x) |
O(log n) | Logarithmic | Grows by one step each time the data doubles. | Binary search in a sorted array |
O(n) | Linear | Grows in step: twice the data, twice the work. | array.includes(x), array.shift(), one loop over everything |
O(n log n) | Linearithmic | Grows a little faster than the data. | array.sort() |
O(n²) | Quadratic | Grows with the square: twice the data, four times the work. | A loop over an array inside another loop over it |
So when a question asks for O(1) operations, it means they must not visit the entries one by one: no indexOf, no includes, no filter, and no shift() or splice() on an array, which move every element after the one removed. Looking a key up in a Map or an object is fine; it's O(1) on average.
Memory is described the same way: O(n) space means the memory used grows in step with the input.
Write two functions that find where a value belongs in an array that's already sorted from smallest to largest. Each takes the sorted array and a value, and returns an index from 0 to array.length. Inserting value at that index keeps the array sorted.
sortedIndex(array, value) returns the lowest such index, which is before any items equal to value. sortedLastIndex(array, value) returns the highest, which is after any items equal to value.
The items and value are all numbers or all strings: compare them with < and >. Neither function changes array.
Both must take O(log n) steps, not O(n): for an array of 1,000 items, read at most 20 of its items. The tests count the reads.
sortedIndex([10, 20, 30, 40], 25); // 2
sortedIndex([1, 2, 2, 2, 3], 2); // 1
sortedLastIndex([1, 2, 2, 2, 3], 2); // 4
sortedIndex(["ant", "cat"], "bee"); // 1
sortedIndex([], 5); // 0
const scores = [10, 20, 30];
scores.splice(sortedIndex(scores, 25), 0, 25);
scores; // [10, 20, 25, 30]
expect(sortedIndex([10, 20, 30, 40], 25)).toBe(2);
expect(sortedLastIndex([10, 20, 30, 40], 25)).toBe(2);
expect(sortedIndex([10, 20, 30, 40], 35)).toBe(3);
expect(sortedIndex([10, 20], 5)).toBe(0);
expect(sortedLastIndex([10, 20], 5)).toBe(0);
expect(sortedIndex([], 5)).toBe(0);
expect(sortedLastIndex([], 5)).toBe(0);
expect(sortedIndex([10, 20], 25)).toBe(2);
expect(sortedLastIndex([10, 20], 25)).toBe(2);
expect(sortedLastIndex([10, 20], 20)).toBe(2);
expect(sortedIndex([1, 2, 2, 2, 3], 2)).toBe(1);
expect(sortedIndex([5, 5, 5], 5)).toBe(0);
expect(sortedIndex([1, 2, 2, 2, 3], 3)).toBe(4);
expect(sortedLastIndex([1, 2, 2, 2, 3], 2)).toBe(4);
expect(sortedLastIndex([5, 5, 5], 5)).toBe(3);
expect(sortedLastIndex([1, 2, 2, 2, 3], 1)).toBe(1);
expect(sortedIndex(["ant", "bee", "cat"], "bat")).toBe(1);
expect(sortedLastIndex(["ant", "bee", "bee", "cat"], "bee")).toBe(3);
const sorted = [0, 0, 2, 4, 4, 4, 6, 8, 10, 10, 11];
for (let value = -1; value <= 12; value += 0.5) {
expect(sortedIndex(sorted, value)).toBe(sorted.filter((item) => item < value).length);
expect(sortedLastIndex(sorted, value)).toBe(sorted.filter((item) => item <= value).length);
}
const data = Array.from({ length: 1000 }, (_, i) => i * 2);
let reads = 0;
const watched = new Proxy(data, {
get(target, key, receiver) {
if (typeof key === "string" && /^\d+$/.test(key)) reads++;
return Reflect.get(target, key, receiver);
},
});
for (const value of [-5, 0, 777, 1000, 1998, 5000]) {
reads = 0;
const index = sortedIndex(watched, value);
expect(reads).toBeLessThanOrEqual(20);
expect(index).toBe(data.filter((item) => item < value).length);
reads = 0;
const lastIndex = sortedLastIndex(watched, value);
expect(reads).toBeLessThanOrEqual(20);
expect(lastIndex).toBe(data.filter((item) => item <= value).length);
}
Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.
Ctrl + Enter runs the tests (⌘ + Enter on a Mac).
I'm here to help with sortedIndex with binary search. I give hints, never the solution, so you get to solve it yourself. Ask for a hint, select code to ask about it, or press Ask Tuto why on a failing test.
Your first 3 answers need no account. for free to keep asking.