Data Structures and Algorithms
Why DSA Matters for Developers
What data structures and algorithms are, and why they are essential for writing efficient, scalable software.
The relationship between problem size and performance — introducing Big O notation: O(1), O(n), O(n²), O(log n), and O(n log n).
How to analyse time complexity and space complexity of code.
Setting expectations: the kind of problems covered in technical interviews at product companies.
Start
Arrays and Strings
Arrays as contiguous memory blocks — indexing, traversal, insertion, and deletion costs.
Common array patterns: two pointers, sliding window, and prefix sums.
String immutability in JavaScript and efficient string manipulation.
Classic problems: reverse an array, find duplicates, maximum subarray (Kadane's algorithm), and anagram detection.
Start
Hash Maps and Sets
How hash tables work: hash functions, buckets, and collision resolution.
JavaScript's Map and Set objects — when to use them over plain objects.
Achieving O(1) average-case lookup, insertion, and deletion.
Classic problems: two-sum, group anagrams, longest consecutive sequence, and frequency counting.
Start
Linked Lists
Singly and doubly linked lists — nodes, pointers, and the trade-offs vs arrays.
Core operations: traversal, insertion at head/tail/middle, deletion, and reversal.
The fast-and-slow pointer (Floyd's tortoise and hare) technique.
Classic problems: detect a cycle, find the middle node, merge two sorted lists, and reverse a linked list.
Start
Stacks and Queues
Stack (LIFO) and queue (FIFO) as abstract data types and their array/linked-list implementations in JavaScript.
The call stack and how recursion uses it.
Monotonic stacks for problems involving next-greater / next-smaller elements.
Classic problems: valid parentheses, implement a queue using stacks, daily temperatures, and the sliding window maximum.
Start
Recursion and Backtracking
The anatomy of a recursive function: base case, recursive case, and the call stack.
Converting recursion to iteration and understanding tail-call optimisation.
Backtracking as a systematic trial-and-error strategy: the decision tree model.
Classic problems: generate all subsets, permutations, combination sum, N-Queens, and Sudoku solver.
Start
Sorting Algorithms
Comparison-based sorts and their complexities: bubble sort, selection sort, insertion sort, merge sort, and quicksort.
In-place vs out-of-place, stable vs unstable sorting.
JavaScript's built-in Array.sort() — its implementation, comparator functions, and gotchas.
Non-comparison sorts: counting sort and radix sort for integers.
Choosing the right sort for the right situation.
Start
Binary Search
The binary search algorithm — preconditions, the mid-point calculation, and avoiding off-by-one errors.
Generalising binary search: searching on a sorted answer space rather than a sorted array.
Classic problems: search in rotated sorted array, find minimum in rotated array, kth smallest element, and capacity to ship packages.
Start
Trees
Tree terminology: root, leaf, depth, height, and subtree.
Binary trees and binary search trees (BST) — properties, insertion, search, and deletion.
Tree traversals: inorder, preorder, postorder (recursive and iterative), and level-order (BFS).
Classic problems: validate a BST, lowest common ancestor, diameter of a binary tree, and maximum depth.
Start
Heaps and Priority Queues
The min-heap and max-heap as complete binary trees stored in an array.
Heap operations: insert (sift-up) and extract-min/max (sift-down) — both O(log n).
Building a priority queue in JavaScript (since the language has no built-in one).
Classic problems: kth largest element, merge k sorted lists, find the median from a data stream, and task scheduler.
Start
Graphs
Graph representations: adjacency list and adjacency matrix — space and time trade-offs.
Directed vs undirected, weighted vs unweighted graphs.
Breadth-First Search (BFS) and Depth-First Search (DFS) — implementation and use cases.
Cycle detection, topological sort (Kahn's algorithm and DFS-based), and connected components.
Classic problems: number of islands, clone graph, course schedule, and word ladder.
Start
Dynamic Programming
Recognising DP problems: overlapping subproblems and optimal substructure.
Top-down DP with memoisation vs bottom-up DP with tabulation.
One-dimensional DP: climbing stairs, house robber, and coin change.
Two-dimensional DP: longest common subsequence, edit distance, 0/1 knapsack, and unique paths.
Optimising space by reducing a 2D table to a 1D array.
Start
Greedy Algorithms
The greedy strategy: making the locally optimal choice at each step and proving it leads to a global optimum.
When greedy works and when it fails — comparing with DP.
Classic problems: activity selection, jump game, gas station, meeting rooms, and Huffman encoding.
Start
Interview Patterns and Problem-Solving
A repeatable framework for tackling unseen problems in an interview: clarify → explore examples → choose a data structure/pattern → code → test → optimise.
The most common patterns summarised: sliding window, two pointers, fast/slow pointer, merge intervals, cyclic sort, BFS/DFS, two heaps, and modified binary search.
Mock interview practice: working through problems aloud, handling hints, and communicating trade-offs.
Curated problem sets by difficulty for continued practice after the course.
Start
