π Day 2: Big O Notation β O(1), O(n), O(nΒ²)
π§ Concept Deep Dive
Big O notation helps us understand how the performance of an algorithm scales with the input size n. It focuses on the worst-case scenario, describing how many operations the algorithm takes as the input grows.
Let's break down the common Big O complexities youβll encounter:
| Big O | Name | Explanation | Example |
|---|---|---|---|
| O(1) | Constant Time | The operation takes the same amount of time regardless of input size | Accessing an element by index |
| O(n) | Linear Time | Time grows linearly with input size β if input doubles, time doubles | Looping through an array |
| O(nΒ²) | Quadratic Time | Time grows with the square of the input size β nested loops over input | Comparing all pairs in an array |
Why Does This Matter?
- Efficiency: When working with large datasets, algorithms with lower Big O will be much faster.
- Predictability: Big O helps predict how your code will perform as data scales.
- Optimization: Understanding complexity guides you to write better, scalable code.
π¨βπ» Code Examples
O(1) β Constant Time
Accessing an element by index in an array takes constant time because you jump directly to it, no matter how big the array is.
function getFirstElement(arr: number[]): number | undefined {
return arr[0]; // Always takes the same time, O(1)
}
// Test
console.log(getFirstElement([10, 20, 30])); // Output: 10O(n) β Linear Time
Looping through an array to calculate the sum of its elements takes time proportional to the number of elements.
function sumArray(arr: number[]): number {
let sum = 0; // O(1)
for (let i = 0; i < arr.length; i++) { // O(n)
sum += arr[i];
}
return sum;
}
// Test
console.log(sumArray([1, 2, 3, 4])); // Output: 10O(nΒ²) β Quadratic Time
When you have nested loops over the same array, the time complexity multiplies.
function printAllPairs(arr: number[]): void {
for (let i = 0; i < arr.length; i++) { // O(n)
for (let j = 0; j < arr.length; j++) { // O(n)
console.log(arr[i], arr[j]); // O(1)
}
}
}
// Test
printAllPairs([1, 2, 3]);
// Output:
// 1 1
// 1 2
// 1 3
// 2 1
// 2 2
// 2 3
// 3 1
// 3 2
// 3 3π ASCII Traces
O(1) β Constant Time
Input: [5, 10, 15]
Access arr[0] β 5
Time taken: Same no matter array sizeO(n) β Linear Time
Input: [1, 2, 3]
Sum elements:
1 + 2 + 3 = 6
Time taken: Proportional to n (3 steps)O(nΒ²) β Quadratic Time
Input: [1, 2, 3]
Pairs generated (nested loops):
(1,1), (1,2), (1,3)
(2,1), (2,2), (2,3)
(3,1), (3,2), (3,3)
Time taken: Number of operations β n * n = 9π Homework (LeetCode-style)
Problem: Count all unique pairs (i, j) in an array where i != j
Function Signature:
function countPairs(arr: number[]): number;Constraints:
- Array length can be from 1 to 10,000.
- Elements are integers.
- Count all ordered pairs
(i, j), whereiandjare indices, andi !== j.
Example 1:
Input: [1, 2, 3]
Output: 6
Explanation: Pairs are (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)Example 2:
Input: [4, 4]
Output: 2
Explanation: Pairs are (0,1), (1,0)π§ BαΊ£ng tΓ³m tαΊ―t Big O
| Operation | Time Complexity | Explanation |
|---|---|---|
| Access by Index | O(1) | Direct access to an element |
| Loop through array | O(n) | One pass through the data |
| Nested loops | O(nΒ²) | Comparing each pair of elements |
π§Ύ Summary
- Big O helps predict how your algorithm performs as data size grows.
- O(1) means constant time β super fast, no matter input size.
- O(n) means linear time β time grows proportionally with input.
- O(nΒ²) means quadratic time β time grows fast due to nested loops.
- Understanding Big O is essential for writing efficient algorithms!
π Coming Up
π Day 3: Arrays β Indexing, Iteration, and Basic Operations
We'll learn how arrays work internally, how to iterate them efficiently, and basic operations every programmer should know.