a system of classifying code to determine which is best (fastest)
a numeric representation of the performance of our code
it’s important to have a precise vocabulary to talk about how our code performs
useful for discussing trade-offs between different approaches
when your code slows down or crashes, identifying parts of the code that are inefficient cant help us find pain points in our applications
using for loop
function upToN(n) {
let total = 0;
for (let i = 1; i <= n; i++) {
total += i;
}
return total;
}
let t1 = performance.now();
addUpTo(1000000000);
let t2 = performance.now();
console.log(`time elapsed: ${(t2 - t1) / 1000} seconds`);
using an expression
function upToN(n) {
return (n * (n + 1)) / 2;
}
let t1 = performance.now();
addUpTo(1000000000);
let t2 = performance.now();
console.log(`time elapsed: ${(t2 - t1) / 1000} seconds`);
function upToN(n) {
return (n * (n + 1)) / 2;
}
Always 3 operations: O(1)
3 operations:
function upToN(n) {
let total = 0;
for (let i = 1; i <= n; i++) {
total += i;
}
return total;
}
Number of inputs is bound by a multiple of n: O(n)
total
i
i <= n
n comparisonstotal in loop
n additionsn assignmentsi in loop
n additionsn assignmentsO(2n) -> O(n), O(500) -> O(1), O(13n^2) -> O(n^2)smaller terms don’t matter O(n + 1000) -> O(n), O(n^2 + 5n + 8) -> O(n^2)
auxiliary space complexity
space required by the algorithm, not the space taken up by the inputs
undefined,null) are constant spaceO(n) space (n is the string length)O(n) where n is the length (for arrays) or number of keys (for objects)O(1) space
function total(int) {
let total = 0;
for (let i = 0; i < int; i++) {
total += i;
}
return total;
}
O(n) space
function double(arr) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
newArr.push(2 * arr[i]);
}
return newArr;
}
the logarithm of a number roughly measures the number of times you can divide that number by 2 before you get a value that’s less than or equal to one
8 / 2; //1
4 / 2; //2
2 / 2; //3
0;
answer: log = 3
for (let i = 0; i < arrayA.length; i++) {
console.log(i);
}
for (let i = 0; j < arrayB.length; j++) {
console.log(j);
}
we do arrayA chunks of work then arrayB chunks of work, therefore the total amount of work is O(A + B)
for (let i = 0; i < arrayA.length; i++) {
for (let j = 0; j < arrayB.length; j++) {
console.log(`${i}, ${j}`);
}
}
we do arrayB chunks of work for each element in arrayA, therefore the total amount of work is O(A * B)
when you see a problem where the number of elements in the problem space gets halved each time, that will likely be a O(log N) runtime
What is k in this expression?
2^k = N
N = 16;
N / 2; // 8
N / 2; // 4
N / 2; // 2
N / 2; // 1
The log expresses 2^4 -> log^2 16 = 4
log^2 N = k -> 2^k = N
nfunction fib(n, memo) {
if (n <= 0) return 0;
else if (n === 1) return 1;
else if (memo[n] > 0) return memo[n];
memo[n] = fib(n - 1, memo) + fib(n - 2, memo);
return memo[n];
}
function allFib(n) {
const memo = [];
for (let i = 0; i < n; i++) {
console.log(`${i}: ${fib(i, memo)}`);
}
}