Problem Solving
problem-solving
Foundations
Algorithms and Efficiency
You already know how to write code that works. But here is a question most beginners never ask: *does it matter how you solve it?* If two programs both give the correct answer, are they equally good? The answer, it turns out, is a decisive no -- and understanding why is the foundation of everything in this course. **Algorithms and Efficiency** is the opening lesson of the DSA Foundations track. Rather than jumping straight into notation or formulas, it starts with a simple, concrete idea: different solutions to the same problem can do very different amounts of work, and that gap in effort becomes enormous once your input is large. You will see two approaches to finding the maximum number in a list, watch the operation counts diverge as the list grows, and come away with a clear intuition for what "efficiency" means in practice. No O() notation yet -- just the honest, visual realization that some code does way more work than it needs to. This lesson bridges everything you already know about writing code to the new skill of *reasoning about* code. You can write loops, call functions, and store values in variables -- that is all you need. By the end, you will have a concrete sense of what engineers mean when they say one algorithm is "better" than another, and you will understand exactly why input size is the key variable in that judgment. Next up is **Counting Operations** (lesson 2), where you will formalize the intuition you build here by learning to count steps precisely as a function of the input size `n`. From there, the track moves into Asymptotic Analysis and Big-O Notation -- the symbolic language the entire industry uses to express these ideas.
Not Started
0%
Debugging by Tracing
Most beginners debug by staring at their code and hoping the bug reveals itself. Engineers who ship working software do something different: they trace execution one line at a time, watch each variable, and pinpoint the exact moment the program's state stops matching their mental model. That motion is a learnable, repeatable skill. **Debugging by Tracing** turns that skill into a structured workflow. You will define what program state actually is (the values of every variable plus the current line of execution), practice walking through a function step by step recording each change, and learn to use loop invariants (conditions that must hold before and after every iteration) to verify correctness without running the code. You will work through a systematic process of reproduce, trace, locate, fix, and verify, and you will see the most common beginner pitfalls including off-by-one errors, uninitialized variables, and misordered swaps. In **How to Read Code (JS & Python)**, you practiced tracing variables through `for` and `while` loops and stepping through function calls on the call stack. This lesson takes that same tracing motion and aims it at a specific goal: finding the line where a bug first introduces wrong state, instead of just understanding what correct code is doing. With Tier 1 essentials behind you, you will be ready to dive into the data structures track starting with **Arrays & Strings**, where every algorithm you write will benefit from being traceable and provably correct.
Not Started
0%
Algorithms
Approximation Algorithms
Vertex Cover is NP-hard: there is no known polynomial algorithm that finds a minimum cover. But a five-line greedy algorithm guarantees a cover whose size is at most twice the minimum, and the proof fits on a napkin. That guarantee, the approximation ratio, is the difference between a heuristic that might be terrible and an algorithm with a written contract about how far from optimal its answer can be. **Approximation Algorithms** introduces that contract-based view of NP-hard optimization. You will define approximation ratio formally and walk through the classic constant-factor algorithms: a 2-approximation for Vertex Cover via greedy maximal matching, an `O(log n)`-approximation for Set Cover via greedy element-counting, and a 2-approximation for Metric TSP that exploits the triangle inequality on top of an MST. The lesson then covers approximation schemes (PTAS, polynomial in `n` for any fixed `epsilon`; FPTAS, polynomial in both), with Knapsack FPTAS as the canonical example. Throughout, the lesson contrasts approximation algorithms with heuristics, where heuristics give no guarantee at all. In **Greedy (Intro)**, you saw simple greedy strategies and their correctness proofs. **Dynamic Programming (Advanced)** introduced 0/1 Knapsack as an NP-hard exact algorithm. This lesson asks the next question: when exact is too slow, how close to optimal can we provably get? Next, **Advanced Bit Manipulation** turns to bit-level tricks for `O(1)` and bitmask-DP solutions.
Not Started
0%
Backtracking (Intro)
Listing every subset of a 20-element set produces over a million results, and there is no shortcut: you have to enumerate them. The trick is to do it without writing 20 nested loops. Backtracking solves the entire family of "generate all configurations" problems with a single recursive template that walks an implicit decision tree. **Backtracking (Intro)** introduces that template as the "choose, explore, unchoose" pattern. You will see how each recursive frame picks an option, recurses into the resulting state, and then undoes the choice on the way back up so the next branch starts from a clean slate. Classic problems include generating all subsets and permutations, the N-Queens placement puzzle, and a first look at Sudoku. The lesson also introduces pruning, where invalid partial solutions are cut off early so the algorithm explores far less than the full `O(2^n)` or `O(n!)` worst case. In **Recursion Fundamentals**, you learned to define a problem in terms of smaller subproblems. Backtracking adds one more idea: state mutated during recursion has to be restored before returning, so siblings in the call tree see the same starting state. From here, **BFS & DFS (Intro)** generalizes the same tree-of-states view to actual graphs.
Not Started
0%
Binary Search Templates
Standard binary search returns an arbitrary index of a target if duplicates exist, but real problems usually want the _first_ such index, the _last_ such index, or the smallest capacity that ships every package within `D` days. Each variation needs a slightly different loop condition and return value, and getting one wrong produces an off-by-one bug or an infinite loop. **Binary Search Templates** turns those variations into a small set of memorable templates. You will work through first and last occurrence with `<=` versus `<` loop conditions, lower bound and upper bound (the templates behind Python's `bisect_left` and `bisect_right`), binary search on the answer space (the "minimize the maximum" pattern that solves Koko Eating Bananas, Capacity to Ship Packages, and Split Array Largest Sum), and search in rotated sorted arrays where the invariant holds for exactly one half at each step. In **Binary Search (Intro)**, you wrote the canonical exact-match loop and learned why it is `O(log n)`. This lesson keeps the halving idea but switches the question from "is `target` here?" to "what is the smallest index that satisfies a monotonic predicate?". Next, **Linked List Algorithms** turns to pointer manipulation patterns.
Not Started
0%
Branch and Bound
0/1 Knapsack is exponentially many subsets to consider, but commercial solvers like CPLEX and Gurobi answer instances with thousands of items in seconds. The trick is not better hardware but smarter exploration: at every node of the search tree, compute a cheap upper bound on what any completion of the partial solution could possibly achieve, and prune the entire subtree if that bound cannot beat the best solution found so far. That single discipline of provably-suboptimal pruning is what defines branch and bound. **Branch and Bound** introduces the framework as a refinement of backtracking. You will design bounding functions (typically a relaxation, like fractional knapsack as a bound for 0/1 knapsack), build state-space trees, and choose between three exploration strategies: FIFO (BFS-like), LIFO (DFS-like), and least-cost (priority queue). Classic applications include 0/1 Knapsack with the fractional-relaxation bound, the Traveling Salesman Problem, and the job-assignment problem. The lesson also draws the line between B&B and DP so you know when each is the right approach. In **Backtracking (Intro)**, you walked an implicit decision tree with choose, explore, unchoose. **Greedy (Intro)** taught you that locally optimal choices sometimes give global optima. Branch and bound borrows the search structure of one and the bounding intuition of the other. Next, **Divide and Conquer (Advanced)** turns to algebraic D&C tricks like Karatsuba and Strassen.
Not Started
0%
Computational Geometry
The sign of a single 2D cross product tells you whether three points turn left, turn right, or are collinear, and that one signed scalar is the workhorse behind almost every algorithm in the plane. Convex hulls, polygon area, segment intersection, and point-in-polygon tests all reduce to a sequence of cross-product evaluations with a careful eye on edge cases. Get the geometric primitive right and the rest of the field follows. **Computational Geometry** introduces those primitives and the algorithms built on them. You will start with cross products and the orientation test, then implement convex-hull algorithms three ways: Graham scan in `O(n log n)` (sort by polar angle, maintain a stack with the orientation invariant), Jarvis march in `O(nh)` for hulls with few vertices, and Andrew's monotone chain. The lesson then covers line-segment intersection, the sweep-line algorithm for many segments, the closest-pair-of-points algorithm in 2D, polygon computations using the Shoelace formula, and the ray-casting point-in-polygon test. In **Sorting (Elementary)**, you learned the comparison-based sorting that drives polar-angle preprocessing. **Divide and Conquer (Advanced)** taught you the closest-pair `O(n log n)` template via the strip combine step, which reappears here. Next, **Advanced Tree Algorithms** moves from planar geometry back to hierarchical structures with Binary Lifting and centroid decomposition.
Not Started
0%
Divide and Conquer (Advanced)
Multiplying two `n`-bit integers the way you learned in school takes `O(n^2)` digit operations. In 1960, Karatsuba showed that the same product can be computed with three recursive multiplications instead of four, dropping the cost to `O(n^1.585)`. A few years later Strassen pulled the same trick on matrix multiplication, replacing eight recursive multiplications with seven and breaking the `O(n^3)` barrier for the first time. Both algorithms are pure divide-and-conquer with cleverly engineered combine steps, and they remain the gateway to a deeper view of D&C as algebraic restructuring. **Divide and Conquer (Advanced)** walks through that view. You will derive Karatsuba multiplication and apply the Master Theorem to its `T(n) = 3T(n/2) + O(n)` recurrence. You will work through Strassen's seven-multiplication identity for `2 x 2` blocks and discuss when its higher constant factor pays off in practice. You will solve closest-pair-of-points in 2D in `O(n log n)` via the strip optimization in the combine step, and look at convex-hull computation through a divide-and-conquer lens. In **Divide and Conquer (Intro)**, you applied the Master Theorem to merge sort and quick sort. **Recursion Fundamentals** gave you the call-stack model these algorithms still inhabit. This lesson keeps the recurrence framework but engineers cleverer combine steps. Next, **Mathematical Algorithms** turns to number-theoretic computation.
Not Started
0%
Greedy (Intro)
Given coin denominations of 1, 5, and 25, the greedy "take the largest coin that fits" strategy gives change optimally. Add a coin worth 10 to the system and greedy stays optimal. Replace 25 with 21 and greedy quietly breaks: making 63 cents now wants three 21s, but greedy says one 21 plus two 1s and ten more 1s. The same algorithm, the same input shape, and yet correctness depends entirely on a structural property of the problem. **Greedy (Intro)** explains exactly which property that is. You will learn to test for the greedy-choice property and optimal substructure, the twin ingredients that justify a greedy decision. The lesson covers the canonical problems where greedy provably works (activity selection by earliest end time, fractional knapsack by value-to-weight ratio, job scheduling with deadlines, the jump game, Huffman encoding) and walks through the exchange-argument style of correctness proof. It also shows where greedy fails (0/1 knapsack, coin change with arbitrary denominations) so you know when to reach for DP instead. In **Sorting (Elementary)**, you saw why sorting often costs `O(n log n)`; almost every greedy algorithm starts with a sort step. **Big-O Notation (Upper Bound)** gave you the language to express that cost. Next, **Dynamic Programming (Intro)** picks up where greedy fails, when the local optimum does not guarantee the global one.
Not Started
0%
Hashing Techniques
Two Sum was a hard problem in 2010. With a hash map it becomes a six-line interview warm-up: walk the array once, and for each value `x` ask whether `target - x` is already in the map. The same shape, single-pass plus complement lookup, solves "first duplicate," "contains nearby duplicate," "longest substring without repeats," and an entire family of trade-space-for-time problems. **Hashing Techniques** catalogs those patterns. You will work through frequency counting (most/least frequent element, group anagrams via sorted-key trick), the two-sum complement template and its three-sum / four-sum extensions, existence checking and duplicate detection, index mapping where you store positions alongside values, and a first conceptual look at rolling hashes that prepare you for Rabin-Karp later. The lesson also discusses when a hash map is overkill versus when it is the obviously correct tool. In **Hash Map (Dictionary) Basics**, you saw how hashing achieves expected `O(1)` insertion and lookup. This lesson is where that constant-time primitive turns into algorithmic leverage: brute-force `O(n^2)` scans collapse into a single pass that uses the map as an oracle. From here you move into the paid track with **Sorting (Advanced)**, which trades hash-map lookups for divide-and-conquer to break the `O(n^2)` sorting barrier.
Not Started
0%
Behavioral Interviews
Solving Complex Technical Problems
Complex-problem questions are the technical-depth probe at the heart of every senior engineering interview. They test whether you can decompose a hard, novel problem under uncertainty, validate hypotheses cheaply, and demonstrate technical depth without over-explaining. This lesson defines what actually counts as 'complex' (scale, novelty, blast radius, time-pressure, multi-component coupling), walks through the four-phase arc (decompose, hypothesise, validate, iterate) you can apply to any technical-depth answer, covers when to mention specific technologies (yes when relevant, no when flexing), and provides fully worked model STAR answers for the prompts you will hear most. After this lesson you will be able to take any genuinely hard problem from your career and tell the story so the rubric reads depth, structure, and judgement simultaneously.
Debugging & Production Incident Stories
Production-incident questions are the operational-judgement probe. They test whether you can act calmly under live pressure, separate mitigation from root-cause work, and tell a blameless story that distinguishes systems-level lessons from individual blame. This lesson defines incident-grade storytelling (timeline craft with explicit T+0 / T+5 / T+30 markers), draws the line between fix, remediation, and prevention, walks through blameless-postmortem language you can use in the room without sounding rehearsed, and provides fully worked model STAR answers for the prompts you will hear most. Every model answer in this lesson focuses blame on systems and processes, never on people or teams. After this lesson you will be able to take any real incident from your career and shape it into an answer that scores on calm, judgement, and operational maturity simultaneously.
