The DSA Problem-Solving Roadmap

Hi everyone ✋

Welcome to a brand-new series ─ problem solving 🧩!

This is where C++ stops being about syntax and starts being about thinking. We’re going to learn data structures and algorithms the way they’re actually used ─ by solving real problems. And we won’t wander through them randomly; we’ll follow a proper roadmap, one clear stop at a time, and solve real LeetCode problems for every topic along the way 🗺️.

Whether you’re here to crack coding interviews or simply to become a sharper programmer, today’s post is the map itself ─ where we’re headed, why in this order, and how we’ll approach every problem so that solving becomes a repeatable skill rather than a lucky guess.

Let’s take a deep dive 🦴

Why learn to solve problems? 💪

Before the map, a quick word on why. Learning data structures and algorithms isn’t just about clearing coding interviews (though it absolutely helps with those 😉). It rewires how we think about code. We start seeing the shape of a problem, recognising that “this is really a graph” or “this smells like two pointers,” and reaching for the right tool instantly. It makes us faster, calmer, and far more confident engineers ─ the kind who can look at something unfamiliar and break it down without panic.

The catch is that DSA is enormous, and diving in without a plan is how people burn out. That’s exactly what a roadmap fixes.

Why a roadmap? 🗺️

Data structures and algorithms is a huge landscape, and most of it only makes sense once the earlier pieces are in place. Trying to learn dynamic programming before we’re comfortable with recursion, or graphs before we’ve met queues and stacks, is like trying to run before we can walk ─ frustrating and slow.

A roadmap solves this by giving us order. Each topic builds on the ones before it, so by the time we reach the hard stuff, we’ve already got every ingredient we need. We’re going to follow a well-proven progression of 18 topics, starting from the humble array and ending at advanced graphs and dynamic programming. Let’s picture how it fits together.

My little reference ─ a skill tree 🎮

Here’s the picture to keep in mind for the whole series ─ think of our roadmap as a video-game skill tree 🎮.

At the very start, we unlock a few cheap, foundational skills ─ Array & Hashing is the first node, and almost everything else branches off it. Once we’ve got the basics, mid-tier skills open up ─ Trees, Heaps, Graphs ─ each requiring the ones below it. And at the far end sit the “boss-level” skills ─ Advanced Graphs, 2D Dynamic Programming ─ powerful combos that only make sense because we’ve unlocked everything leading up to them.

And every LeetCode problem we solve is like earning XP ⭐ ─ it levels up the skill it belongs to, until the pattern becomes second nature. We don’t grind random problems; we follow the tree, unlocking each node in turn. By the end, the whole tree is lit up 🌳.

Keep that skill tree in mind ─ it’s why we go in this order and not another.

The 18 stops on our roadmap 🧭

Here’s the full map ─ the eighteen topics we’ll conquer, in order, with a one-line taste of each. Every one of these will become its own deep-dive post with worked LeetCode problems.

  1. Array & Hashing ─ the foundation; storing data and looking it up instantly with hash maps and sets.
  2. Two Pointers ─ two indices walking through an array to solve in one clean pass.
  3. Stack ─ last-in-first-out; the tool for matching, parsing, and “nearest” problems.
  4. Binary Search ─ halving a sorted search space for lightning-fast O(log n) lookups.
  5. Sliding Window ─ a moving range over an array or string for subarray and substring problems.
  6. Linked List ─ nodes chained by pointers; reversal, cycle detection, merging (our pointers series pays off here 😉).
  7. Trees ─ hierarchical data; traversal, recursion, and binary search trees.
  8. Tries ─ prefix trees that make word and prefix lookups blazingly fast.
  9. Heap / Priority Queue ─ always grab the smallest or largest in a snap; top-K and scheduling.
  10. Backtracking ─ try, recurse, undo; explore every combination and permutation systematically.
  11. Intervals ─ merging, overlapping, and scheduling ranges.
  12. Greedy ─ make the best local choice at each step and trust it leads somewhere good.
  13. Graphs ─ nodes and edges; BFS, DFS, connectivity, and shortest paths.
  14. Advanced Graphs ─ Dijkstra, minimum spanning trees, topological sort, and the heavier hitters.
  15. 1D Dynamic Programming ─ breaking a problem into overlapping subproblems along a single dimension.
  16. 2D / Multi-dimensional DP ─ the same idea across grids and pairs of sequences.
  17. Bit Manipulation ─ working directly with bits for clever, blazing-fast tricks.
  18. Math & Geometry ─ number theory, coordinate tricks, and matrix manipulations.

Eighteen stops, and by the last one we’ll be tackling problems that would’ve looked terrifying on day one 🥳.

Why this order? 🔢

The sequence isn’t random ─ it climbs deliberately from foundations to the toughest peaks. Reading the map in tiers makes the logic clear ─

  • The foundation (1)Array & Hashing. Hashing shows up in almost every other topic, so we master it first.
  • Core array patterns (2‑5)Two Pointers, Stack, Binary Search, Sliding Window. These are techniques that operate on the arrays and strings we just learned to handle.
  • A linear structure (6)Linked List. Our first pointer-based structure, and a natural bridge from arrays to more complex shapes.
  • Non-linear structures (7‑9)Trees, Tries, Heaps. These lean on recursion and the linear structures below them.
  • Algorithmic strategies (10‑12)Backtracking, Intervals, Greedy. General problem-solving techniques rather than data structures.
  • Graphs (13‑14)Graphs then Advanced Graphs. The most general structure of all, and graph traversal reuses the queues, stacks, and heaps we’ve already met.
  • Dynamic Programming (15‑16)1D then 2D DP. The famous “final boss,” built entirely on recursion plus a memory of past results.
  • Specialised toolkits (17‑18)Bit Manipulation and Math & Geometry. Focused skills that sharpen the rest.

Notice how each tier reuses the ones beneath it. Graphs need queues and stacks; DP needs recursion; advanced graphs need heaps. That’s the skill tree in action ─ nothing later works without the nodes below it 🎮.

How we’ll crack every problem ─ a repeatable method 🧠

Here’s the most important idea in this whole series ─ solving problems is a method, not magic. The goal isn’t to memorise a thousand solutions; it’s to build a reliable process we can apply to any problem, even one we’ve never seen. Throughout the series, we’ll follow the same steps ─

  1. Understand it. Restate the problem in our own words. What are the inputs, the outputs, the constraints?
  2. Work a small example by hand. Nothing beats pen and paper for spotting the pattern.
  3. Start with brute force. Get any working solution first, however slow. A correct slow answer beats a broken clever one.
  4. Find the bottleneck and optimise. Ask “what work am I repeating?” ─ that repeated work is almost always where a better data structure or pattern hides.
  5. Code it cleanly, then test the edge cases ─ empty input, one element, duplicates, the largest allowed size.
  6. Analyse the cost ─ the time and space complexity, so we know how good our answer really is.

Let’s see steps 3 and 4 in miniature. Suppose we just want to know “does this array contain any duplicate?” The brute-force idea is to compare every pair ─

// Brute force ─ O(n²): compare every pair of elements
bool hasDuplicateBrute(vector<int>& nums) {
    for (size_t i = 0; i < nums.size(); i++)
        for (size_t j = i + 1; j < nums.size(); j++)
            if (nums[i] == nums[j]) return true;
    return false;
}

That works, but it repeats a lot of comparisons. The bottleneck question ─ “what am I repeating?” ─ points us straight at a hash set: instead of re-scanning, we just remember what we’ve already seen.

// Optimised ─ O(n): remember what we've seen in a hash set
bool hasDuplicateFast(vector<int>& nums) {
    unordered_set<int> seen;
    for (int n : nums) {
        if (seen.count(n)) return true;   // seen it before ─ duplicate!
        seen.insert(n);
    }
    return false;
}

Same answer, but we went from O(n²) down to O(n) ─ and the entire leap came from one question: what work was I repeating? That single habit, asked over and over, is what this series is really teaching 🥳. (And yes ─ that unordered_set is straight from our STL series.)

A quick primer on Big-O ⏱️

Since we’ll measure every solution by its cost, let’s pin down Big-O notation ─ a way to describe how an algorithm’s work grows as the input grows. We ignore constants and focus on the shape of the growth. Here are the ones we’ll meet constantly ─

Big-O Name Feels like Example
O(1) constant instant indexing an array
O(log n) logarithmic wonderful binary search
O(n) linear fine one pass over the data
O(n log n) linearithmic good an efficient sort
O(n²) quadratic careful nested loops over the data
O(2ⁿ) exponential alarming trying every subset naively

The rough goal in most problems is to push down this ladder ─ turning an O(n²) brute force into an O(n log n) or O(n) solution, exactly like the duplicate example above. We’ll also track space complexity the same way ─ the extra memory a solution uses (that hash set costs O(n) space to save all that time). Speed and memory are a trade, and naming both is how we judge a solution honestly.

What we’ll need 🧰

This series assumes we’re comfortable with a few things, and happily we’ve built them together already ─

  • Solid C++ basics ─ variables, loops, functions, and classes.
  • The STL ─ we’ll lean heavily on vector, unordered_map, unordered_set, stack, queue, and priority_queue. Our C++ STL series is the perfect companion.
  • Pointers and references ─ especially once we reach linked lists and trees. The pointers series has us fully covered there.

If any of those feel shaky for you, a quick detour through those series first will make everything here click faster. And of course, every solution we write will be plain, readable C++ ─ no clever one-liners for their own sake, just clear code we can learn from.

So what should we remember? 🤔

Let’s wrap up the plan ─

  • We’re starting a problem-solving series ─ learning data structures and algorithms by solving real LeetCode problems, in C++.
  • We follow a roadmap of 18 topics so each idea builds on the last ─ think of it as a skill tree 🎮 where early nodes unlock the advanced ones.
  • The order climbs from Array & Hashing through patterns, structures, strategies, graphs, and dynamic programming, up to specialised toolkits ─ each tier reusing the ones beneath it.
  • The heart of the series is a repeatable method ─ understand, try a small example, brute force, find the repeated work, optimise, test edges, and analyse cost ─ not memorising solutions.
  • We measure everything with Big-O, aiming to trade a little space to climb down from O(n²) toward O(n log n) or O(n).
  • We’ll build on our C++, STL, and pointers foundations throughout.

The real prize isn’t a pile of solved problems ─ it’s the pattern recognition that lets us look at something brand new and think, calmly, “I’ve got a way in.” 👀✨

Congratulations 🥳🥳🥳
We’ve got our map, our method, and our mindset ─ everything we need to begin.

In the next post we take our very first step onto the roadmap ─ Array & Hashing ─ the foundation the entire tree grows from. We’ll cover it inside out and solve our first batch of LeetCode problems together 😉

Happy Coding 💻 🎵

Leave a Comment

Your email address will not be published. Required fields are marked *