Blog · June 22, 2026
5 Algorithms Every Developer Should Actually Understand (Not Just Memorize)
You don’t need to memorize every algorithm out there. You need to know which tool fits which problem, and be able to explain why.
This post covers five: Breadth First Search (BFS), Dijkstra’s algorithm, greedy algorithms, dynamic programming, and binary search trees. Each one solves a different kind of problem. By the end, you’ll know which one to use and when.
1. BFS: Find the Shortest Path When Every Step Costs the Same
What it does: BFS finds the shortest path between two points in a graph, where “shortest” means fewest steps.
That could be the fewest moves to win a game, the fewest edits to fix a typo, or the shortest chain of connections between two people on a network.
A graph is just nodes connected by edges. BFS answers two questions: is there a path between two nodes, and if so, what’s the shortest one?
How it works:
BFS uses a queue (first in, first out) and searches level by level, not path by path. Represent the graph as a hash table, with each node pointing to a list of its neighbors. Then:
- Add the starting node’s neighbors to the queue.
- Pull the next item off the queue.
- Already checked it? Skip it.
- Is it the target? Return true.
- If not, add its neighbors to the queue.
- Mark the current node as checked.
- Repeat until you find the target or the queue runs dry.
If the queue empties out with no match, return false.
Two details that trip people up:
- Track what you’ve already visited. Skip this and you’ll end with a loop, revisiting the same nodes.
- Order matters. BFS only guarantees the shortest path because it processes nodes in the order they were added.
Graphs can be directed (one-way relationships, like “follows” on social media) or undirected (two-way, like “friends” on Facebook).
Time complexity: O(V + E), where V is vertices and E is edges.
Rule of thumb: if a problem is really asking “what’s the fewest steps to get from A to B,” it’s probably a graph problem, and BFS should be your first move.
2. Dijkstra’s Algorithm: Same Idea, But the Steps Aren’t Equal
BFS assumes every edge costs the same. Real life rarely works that way. A route with fewer turns might take longer than one with more turns but faster roads.
That’s the problem Dijkstra’s algorithm solves: the cheapest or fastest path through a graph where edges have different weights.
The rule for choosing between them:
- No weights, all steps equal: BFS
- Weights, but all non-negative: Dijkstra’s
If you’ve got negative weights in the problem, Dijkstra’s breaks down. Look at Bellman-Ford instead.
How it works:
- Pick the node with the lowest known cost.
- Check whether reaching its neighbors through it is cheaper than what you had before.
- Update the neighbor’s cost if it is.
- Repeat until every node’s been processed.
- Reconstruct the path from your records.
Once a node’s cost is finalized, it stays finalized. No cheaper route will show up later.
What you need to build it:
Three hash tables: one for the graph itself, one tracking current cheapest costs, one tracking each node’s parent (so you can rebuild the final path afterward). An array tracks which nodes are already processed.
In Python, float('inf') is your starting cost for every node except the source.
3. Greedy Algorithms: Good Enough, Fast
A greedy algorithm doesn’t try to solve the whole problem at once. It just picks whatever looks best right now, one step at a time, and hopes that adds up to a great overall answer.
Sometimes it does. Sometimes it gets close. It’s not guaranteed to be perfect, and that’s the tradeoff: speed and simplicity in exchange for giving up the guarantee of the best possible answer.
Reach for greedy when you want something simple, fast, and “good enough” beats “perfect but slow.”
Example: scheduling classes
You’ve got a room and a pile of classes that overlap. You want to fit in as many as possible.
- Pick the class that ends soonest.
- From what’s left, pick the next one that starts after your last pick and ends soonest.
- Repeat until nothing fits.
Each choice is locally optimal, earliest finish time, and it works out to a solid overall schedule.
Greedy as an approximation strategy
Some problems are just too slow to solve exactly. Greedy gives you a fast, close-enough answer instead. You judge these approximations on two things: how fast they run, and how close they land to optimal.
Example: covering all 50 states with the fewest radio stations
- Pick the station covering the most states you haven’t covered yet.
- Don’t worry if it overlaps with states you’ve already got.
- Repeat until every state’s covered.
Example: the Traveling Salesman Problem
- Start somewhere.
- Go to the nearest city you haven’t visited.
- Repeat until you’ve hit every city.
Fast and simple. Not the shortest possible route.
4. Dynamic Programming: Solve the Small Version First
Dynamic programming works when a big problem breaks down into smaller, overlapping versions of itself. Solve the small ones, use those answers to build up to the big one.
It’s especially useful for optimization problems with a constraint attached: maximize this, but you’re limited to that.
Example: the knapsack problem
You’re a thief with a knapsack that holds a fixed amount of weight. You want to grab the combination of items that gets you the most value without going over the limit.
Instead of testing every possible combination, dynamic programming builds the answer up from smaller versions of the same problem (what’s the best you can do with a smaller bag, or fewer items to choose from) and works up to the full one.
Most DP problems get modeled as a grid, where each cell is a subproblem and the values represent whatever you’re optimizing. The real skill here isn’t the code, it’s figuring out how to break the big problem into the right smaller ones. There’s no universal formula. Every problem breaks down differently.
5. Binary Search Trees: Structure That Keeps Search Fast
A binary search tree (BST) organizes data with one rule: smaller values go left, bigger values go right.
That simple rule is what makes searching fast.
A balanced BST gets you:
- O(log n) search
- O(log n) insertion
- O(log n) deletion
Why not just use a sorted array?
You can binary search a sorted array in O(log n) too. The problem shows up when you need to insert something new: you often have to shift a bunch of elements around to keep the array sorted.
A BST skips that. Insert or delete a node, and you’re not reorganizing the whole structure, just adjusting local connections.
Quick Reference: Which One Do You Need?
| Problem | Use |
|---|---|
| Shortest path, all steps equal | BFS |
| Shortest or cheapest path, weighted, non-negative | Dijkstra’s algorithm |
| Fast, good-enough answer; local choices add up | Greedy algorithm |
| Big problem breaks into smaller overlapping ones, with a constraint | Dynamic programming |
| Need fast search, insert, and delete on ordered data | Binary search tree |
FAQ
What is BFS used for?
Finding the shortest path between two nodes in an unweighted graph, meaning the path with the fewest edges.
What’s the difference between BFS and Dijkstra’s algorithm?
BFS finds the path with the fewest edges, and only works when every edge is worth the same. Dijkstra’s finds the cheapest or fastest path when edges have different weights (as long as none are negative).
What is a greedy algorithm?
An algorithm that picks the best-looking option at each step, aiming for an optimal or near-optimal result overall. It’s fast and simple, but not guaranteed to be perfect.
When should I use dynamic programming?
When a problem can be broken into smaller, overlapping subproblems, and you’re optimizing something under a constraint.
What is a binary search tree?
A tree where every node’s smaller values sit to its left and larger values sit to its right, which keeps search, insertion, and deletion fast when the tree is balanced.
What is the time complexity of BFS?
O(V + E), where V is the number of vertices and E is the number of edges.