DEV Community

Cover image for Why Algorithms Matter
Rosebella Wandere
Rosebella Wandere

Posted on

Why Algorithms Matter

Why Algorithms Matter: What a Sorting Project Taught Me About Programming

When I started learning programming, I thought most problems could be solved by just writing enough code. Eventually I realized something important: the hardest part isn't always writing the code , it's deciding what the code should do. That's where algorithms come in.

While working on a sorting project recently (a Push-Swap implementation, where you sort numbers using two stacks and a limited set of operations), I had to think hard about different ways to sort data, how those approaches scale, and how to work within strict constraints. What caught my attention was the algorithmic thinking behind it, and that's what I want to share.

What Exactly Is an Algorithm?

An algorithm is a step-by-step procedure for solving a problem. Say you have 5 2 8 1 3 and you need 1 2 3 5 8. Getting there is straightforward in principle, but there are many ways to do it:

  • Repeatedly find the smallest value and place it.
  • Compare neighboring values and swap them.
  • Divide the problem into smaller pieces and merge the results.
  • Process the digits or bits of each number instead of comparing whole values.

All of these produce the same result. What makes algorithms interesting is how they get there and that difference has real consequences for performance.

The Same Problem, Very Different Solutions

A simple sorting approach is Bubble Sort: repeatedly compare neighboring elements and swap them if they're in the wrong order.

For 5 2 8 1:

5 2 8 1  → compare 5,2 → 2 5 8 1
2 5 8 1  → compare 5,8 → 2 5 8 1
2 5 8 1  → compare 8,1 → 2 5 1 8
Enter fullscreen mode Exit fullscreen mode

Keep repeating until nothing needs swapping. It works, but its worst-case time complexity is O(n²), which gets expensive fast as n grows. This raises a real developer question: if two algorithms solve the same problem, which one should you choose?

Complexity Changes Everything

Say Algorithm A runs in O(n²) and Algorithm B runs in O(n log n). For small inputs, the difference barely matters. At n = 1,000, though:

n²        = 1,000,000
n log₂n  ≈    10,000
Enter fullscreen mode Exit fullscreen mode

That's a huge gap in work done. This is why understanding time complexity matters. Correct code can still be a poor solution if it doesn't scale.

Big O Isn't About Exact Seconds

One common misunderstanding is that Big O tells you exactly how many seconds an algorithm takes. It doesn't, instead it describes how the amount of work grows relative to input size.

O(1) — constant time. Work doesn't grow with input size.

value := numbers[0]
Enter fullscreen mode Exit fullscreen mode

O(n) — linear time. Double the input, roughly double the work.

for _, number := range numbers {
    // process number
}
Enter fullscreen mode Exit fullscreen mode

O(n²) — quadratic time. Double the input, and the work can roughly quadruple.

for i := 0; i < n; i++ {
    for j := 0; j < n; j++ {
        // work
    }
}
Enter fullscreen mode Exit fullscreen mode

O(log n) — logarithmic time. Binary search is the classic example: instead of checking every element, you eliminate half the remaining search space each step (1,000,000 → 500,000 → 250,000 → ... → 1). The core idea: don't just make progress, eliminate unnecessary work.

Selection Sort: Simple but Expensive

Selection Sort repeatedly finds the smallest remaining element and moves it into place. For 4 2 7 1 5, you find 1, move it to the front, then find the next smallest, and so on.

It's easy to understand and implement, but it performs roughly n²/2 comparisons, still O(n²). For small collections that's often fine. For large ones, it's a sign to look for something better. Lesson: the simplest algorithm isn't always the best one.

Divide and Conquer

Merge Sort is a classic divide-and-conquer algorithm: split the data into smaller pieces, sort those, then merge them back in order.

[8 3 5 1 4 2]
   /       \
[8 3 5]   [1 4 2]
 /   \      /   \
...  ...  ...  ...
   \       /
    merge
      |
[1 2 3 4 5 8]
Enter fullscreen mode Exit fullscreen mode

Merge Sort runs in O(n log n) in both the average and worst cases.This is a meaningful improvement over quadratic sorts like bubble sort and selection sort for large datasets, though it typically needs extra memory for merging.

Radix Sort and Binary Representation

One of the more interesting algorithms I ran into is Radix Sort. Unlike Bubble or Merge Sort, it doesn't compare elements directly, it sorts based on their representation, digit by digit or bit by bit.

For binary Radix Sort, take 2, 3, 4, 5:

2 → 010
3 → 011
4 → 100
5 → 101
Enter fullscreen mode Exit fullscreen mode

Process one bit position at a time, starting from the least significant bit. Partition the numbers by whether that bit is 0 or 1, then move to the next bit, and the next. After processing all bit positions, the numbers end up sorted.

The key idea: instead of comparing whole numbers, you can process a small part of their representation at each stage. This works because integers have structure you can exploit, you don't always need direct comparisons to organize data.

On complexity: for n numbers with k bits (or digits) each, binary/digit Radix Sort does roughly O(nk) work. k here is the number of bits (or digits) needed to represent the largest value for fixed-size integers (like 32-bit ints), k is a constant, so the sort behaves close to linear in n. But k isn't free: for arbitrarily large or variable-length keys, it matters, and Radix Sort also needs extra space for the buckets/counting step. It's not "always better" it's a good fit for specific kinds of data.

Algorithms Have Trade-Offs

Time complexity isn't the only thing that matters. You should also weigh memory usage, implementation complexity, stability, and how well an algorithm fits your actual data.

Algorithm       Average Complexity
----------------------------------
Bubble Sort     O(n²)
Selection Sort  O(n²)
Merge Sort      O(n log n)
Quick Sort      O(n log n)*
Radix Sort      O(nk)
Enter fullscreen mode Exit fullscreen mode

Quick Sort's worst case is O(n²), depending on pivot choice and implementation.

There's no algorithm that wins in every situation, the "best" one depends on context.

Constraints Can Change the Best Algorithm

If you can use any operation you want, sorting is straightforward. Now imagine you're given two stacks, a limited set of operations, no direct indexing, and a goal of minimizing the number of moves that's roughly the Push-Swap problem. Suddenly the "best" algorithm isn't the one with the best theoretical complexity; it's the one that respects the constraints you actually have.

This happens constantly in real software:

  • Limited memory → pick a memory-efficient algorithm.
  • Huge dataset → pick something that scales well.
  • Low latency requirement → optimize the critical path.
  • Limited bandwidth → reduce the data you transfer.

Constraints aren't just restrictions, they help determine the solution.

Greedy Thinking

A greedy algorithm makes the best-looking choice at each step, without looking ahead. This doesn't always produce a globally optimal result, but for the right class of problems, it does. Recognizing when greedy thinking is appropriate is a skill on its own, and it shows up well beyond sorting in scheduling, resource allocation, shortest-path problems, and compression. At its core, it's a decision-making pattern: look at the current state, pick the best local option, move to the next state, repeat.

Algorithmic Thinking Over Memorization

You don't need to memorize every sorting algorithm. What matters more is asking the right questions when you face a problem:

  1. What's the input? Numbers, strings, graphs, objects, files?
  2. What's the output? What exactly counts as "correct"?
  3. What constraints exist? Memory, time, allowed operations, input size?
  4. What patterns exist in the data? Sorted already? Bounded values? Repeats?
  5. How does the solution scale? What happens at 10 items vs. 1,000,000?
  6. Can you reduce unnecessary work? Often the most important question of all.

Why This Matters Beyond Sorting

You might think: "I build web apps, why do I need sorting algorithms?" The thinking behind them applies everywhere.

If your API searches records, you can scan everything, or use an appropriate data structure and search strategy. If your app recalculates the same expensive result repeatedly, you can compute it every time, or cache it. If you're processing millions of records, you can reach for a quadratic approach, or look for something closer to O(n log n).

The language, framework, or database might change. The core question remains: how do you solve this efficiently, given your constraints?

Algorithms Make You Think Before You Code

Without algorithmic thinking, development can turn into: hit a problem, start coding, something breaks, add more code, add another condition, add another loop, hope it works.

Algorithmic thinking pushes a different process instead: understand the constraints, model the problem, choose a strategy, analyze the complexity, implement, test, optimize if needed. It's a stronger habit, and it pays off even outside classic algorithm problems.

You Don't Need the "Best" Algorithm

It's also easy to over-optimize. Not every problem needs the most sophisticated solution. If you have ten elements, an O(n²) approach might be completely fine. If you have ten million, it's worth thinking harder.

The useful question isn't "what's the fastest algorithm?" it's "what's the appropriate algorithm for this problem?" That's a much more practical engineering mindset.

Final Thoughts

Working through a sorting problem reminded me that algorithms aren't just academic exercises, they're a way of thinking. They teach you to break problems down, recognize patterns, understand constraints, measure complexity, and weigh trade-offs.

Knowing how to write code lets you make a program work. Understanding algorithms lets you ask a better question: will this still work well when the problem gets much bigger? That's the difference between writing code and engineering a solution.

Top comments (0)