DEV Community

Timevolt
Timevolt

Posted on

The Fellowship of Clean Code: Merging Intervals Like a Pro

The Quest Begins (The “Why”)

I still remember my first technical interview like it was yesterday. The interviewer slid over a whiteboard marker and said, “Here’s an array of intervals — merge any that overlap.” My brain went into panic mode. I started scribbling loops inside loops, checking every pair, resetting counters, and before I knew it I had a tangled mess of if‑else statements that looked like a plate of spaghetti after a toddler’s dinner. The interviewer raised an eyebrow, I mumbled something about “edge cases,” and we both knew the solution wasn’t clean enough to pass.

That moment stuck with me because it wasn’t about knowing the algorithm — it was about how I approached the problem. I realized I was missing a mental framework that top coders use instinctively: they don’t jump straight into code; they first understand, visualize, break down, and name each piece before they type a single line.

The Revelation (The Insight)

The breakthrough came when I started treating every interview problem like a quest in a role‑playing game. Instead of charging at the boss with a sword, I first scouted the terrain, identified the patterns, and then equipped myself with the right tools. For merging intervals, the pattern is simple once you see it:

  1. Sort the intervals by their start time.
  2. Walk through the sorted list, keeping a “current” interval that you expand whenever the next one overlaps.
  3. When you hit a gap, you push the current interval onto the result and start a new current interval.

That’s it. No nested loops, no magic numbers, no mutable state flying around everywhere. The aha! moment was realizing that sorting gives us a guarantee: if two intervals can overlap, they will be next to each other in the sorted order. From there, the problem becomes a linear scan — something we can read like a story.

I also adopted a handful of naming and structuring habits that turned the code from “what does this even do?” to “oh, I get it instantly”:

  • Verb‑first function names (merge_intervals, is_overlap).
  • Descriptive variable names (current, merged, next_interval).
  • Early returns for trivial cases (empty input, single interval).
  • Pure functions that don’t mutate the input unless explicitly required.

These aren’t just style tips; they’re cognitive shortcuts that let your brain focus on the logic instead of decoding symbols.

Wielding the Power (Code & Examples)

The Struggle – Before

def merge_intervals_bad(intervals):
    if not intervals:
        return []
    res = []
    i = 0
    while i < len(intervals):
        start, end = intervals[i]
        j = i + 1
        while j < len(intervals):
            s, e = intervals[j]
            if s <= end:               # overlap?
                end = max(end, e)
                start = min(start, s)
                intervals.pop(j)       # mutate while iterating!
            else:
                j += 1
        res.append([start, end])
        i += 1
    return res
Enter fullscreen mode Exit fullscreen mode

What’s happening here?

  • We’re mutating the list while iterating (pop(j)), which is error‑prone and hard to follow.
  • Variable names like i, j, start, end get reused without clear intent.
  • The overlap check is buried inside a nested loop, making the overall O(n²) complexity obvious only after you trace it.

The Victory – After

def merge_intervals(intervals):
    """Return a new list of merged, non‑overlapping intervals."""
    if not intervals:
        return []                     # early exit for empty input

    # 1️⃣ Sort by the start of each interval – O(n log n)
    sorted_intervals = sorted(intervals, key=lambda x: x[0])

    merged = []
    current_start, current_end = sorted_intervals[0]

    for start, end in sorted_intervals[1:]:
        # 2️⃣ If the next interval overlaps, stretch the current one
        if start <= current_end:               # overlap detected
            current_end = max(current_end, end)
        else:                                   # 3️⃣ No overlap – push current and start fresh
            merged.append([current_start, current_end])
            current_start, current_end = start, end

    # Don’t forget the last interval!
    merged.append([current_start, current_end])
    return merged
Enter fullscreen mode Exit fullscreen mode

Why this feels like a spell:

  • The function does one thing and does it well — its docstring tells you exactly what to expect.
  • Sorting isolates the hard part; the subsequent loop is a straightforward scan.
  • Variables like current_start/current_end read like sentences: “If the next interval starts before the current one ends, we stretch it.”
  • No mutation of the original list, no confusing indices, and the runtime is optimal (O(n log n) for sorting, O(n) for the scan).

Common Traps to Avoid

Trap What it looks like Why it’s harmful
Forgetting to sort Trying to merge in original order Overlaps can be missed; you’ll need O(n²) checks.
Mutating while iterating intervals.pop(i) inside a for loop Leads to skipped elements or index errors.
Using magic numbers Hard‑coding 0 or 1 for start/end indices Makes the code brittle if the interval representation changes.
Skipping the final push Leaving the last current interval out of merged You lose the last piece of the answer.

Why This New Power Matters

Adopting this mindset changed my interview game. I stopped feeling like I was guessing and started feeling like I was telling the computer a story — one that it could follow without getting lost. The benefits ripple out:

  • Readability: Future teammates (or your future self) can glance at the code and grasp the intent in seconds.
  • Debugging: When something goes wrong, you know exactly where to look because each step is isolated and named.
  • Confidence: Walking into an interview, you know you have a repeatable process: understand → visualize → break → name → code.

And the best part? This framework works for any problem — strings, trees, dynamic programming, you name it. It’s not a trick; it’s a habit.

Your Turn

Now that you’ve seen the Fellowship in action, I challenge you to pick a problem you’ve struggled with before (maybe “Longest Substring Without Repeating Characters” or “Binary Tree Level Order Traversal”) and apply the same steps:

  1. Draw a few examples on paper or a whiteboard.
  2. Identify the pattern (sorting, sliding window, divide‑and‑conquer, etc.).
  3. Write pseudocode that names each step clearly.
  4. Translate that into clean, readable code.

Drop your before/after snippets in the comments — let’s see who can refactor the gnarliest solution into something elegant. Happy coding, and may your intervals always merge smoothly! 🚀

Top comments (0)