rust 82 lines · 3 tabs

Merging Overlapping Booking Intervals with a Sweep-Line in Rust

Shared by codesnips Jul 2026
3 tabs
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Interval {
    pub start: i64,
    pub end: i64,
}

impl Interval {
    pub fn new(start: i64, end: i64) -> Option<Interval> {
        if end < start {
            return None;
        }
        Some(Interval { start, end })
    }

    pub fn overlaps_or_touches(&self, other: &Interval) -> bool {
        // half-open ranges: touching at a boundary does not overlap
        other.start < self.end
    }

    pub fn merge_with(&mut self, other: &Interval) {
        if other.end > self.end {
            self.end = other.end;
        }
    }
}
3 files · rust Explain with highlit

This snippet shows how a booking schedule is collapsed into a set of non-overlapping busy blocks, a common step before rendering availability or detecting double-bookings. The core idea is the interval-merge algorithm: sort intervals by start time, then walk them once, extending the current block whenever the next interval starts before the current one ends.

The Interval type tab defines a half-open range [start, end) over i64 timestamps (Unix seconds work well). Using a half-open convention matters because two bookings where one ends exactly when the next begins are adjacent, not overlapping, and should stay separate. The overlaps_or_touches method encodes the merge threshold, and merge_with widens the block by taking the maximum end so a short booking nested inside a longer one does not accidentally shrink it.

The merge module tab holds the algorithm itself. merge_intervals first guards the empty case, then sorts a cloned vector by start using sort_by_key. The single pass keeps a mutable current block; each following interval either merges into current via merge_with or is pushed and becomes the new current. Sorting is O(n log n) and dominates the linear scan, which is the standard cost for this problem. Cloning the input keeps the function non-destructive, a reasonable trade-off unless the caller owns a large vector and can afford to sort in place.

A subtle pitfall handled here: because intervals are sorted by start only, the running current.end can exceed the next interval's end, so merge_with must guard with max rather than blindly assigning. Malformed intervals where end < start are rejected by Interval::new returning an Option, keeping bad data out of the merge entirely.

The tests tab exercises the tricky boundaries: fully contained intervals, back-to-back bookings that must not merge, and unsorted input. These cases are where naive implementations usually break, so pinning them down protects against regressions when the algorithm is later optimized.


Related snips

Share this code

Here's the card — post it anywhere.

Merging Overlapping Booking Intervals with a Sweep-Line in Rust — share card
Link copied