Master the building blocks of efficient programming. Visualize, interact, and understand core concepts through minimalist design and clear explanations.
Understanding Big O notation is crucial for analyzing algorithm efficiency. Lower is better.
Execution time stays the same regardless of input size. The holy grail of algorithms.
Doubling the input barely increases runtime. Highly efficient for large datasets.
Runtime grows proportionally with input size. Acceptable for most operations.
Performance degrades rapidly with larger inputs. Avoid for large datasets.
The simplest and most widely used data structure. Elements are stored in contiguous memory locations, allowing instant access via index.
O(1) time to access any element by index
Insertion and deletion are expensive O(n) operations
// Declaration & Initialization
const arr = [10, 20, 30, 40, 50];
// Access (O(1))
console.log(arr[2]); // 30
// Insert at end (O(1))
arr.push(60);
// Search (O(n))
const index = arr.indexOf(30);
A sequence of nodes where each node points to the next. Unlike arrays, elements are not stored contiguously, allowing efficient insertion and deletion.
class Node {
constructor(data) {
this.data = data;
this.next = null; // Pointer to next node
}
}
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
// O(1) insertion at head
prepend(data) {
const newNode = new Node(data);
newNode.next = this.head;
this.head = newNode;
}
}
Last In, First Out. Think of a stack of plates. Operations happen only at the top.
// Operations
stack.push(item); // O(1) - Add to top
stack.pop(); // O(1) - Remove top
stack.peek(); // O(1) - View top
// Use cases: Undo, Browser History,
// Function Call Stack
First In, First Out. Like a line at a ticket counter. Fair and orderly processing.
// Operations
queue.enqueue(item); // O(1) - Add to rear
queue.dequeue(); // O(1) - Remove front
queue.front(); // O(1) - View front
// Use cases: Print Spooling,
// CPU Scheduling, BFS
A node-based structure where each node has at most two children. Left child is smaller, right child is larger. Enables efficient searching.
* Assuming balanced tree. Worst case O(n) for skewed tree.
class TreeNode {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
// Inorder traversal
// Left -> Root -> Right
// Gives sorted order
Visual comparison of different sorting approaches. Click to see them in action.
Repeatedly steps through the list, compares adjacent elements and swaps them if they are in the wrong order.
Divide and conquer algorithm. Picks an element as pivot and partitions the array around it.
Divides the array into halves, sorts them and then merges them back together.