Given intervals, select the maximum number of pairwise non-overlapping ones.

The algorithm — sort by finish time

int maxNonOverlapping(vector<pair<int,int>> iv) {         // (start, end)
    sort(iv.begin(), iv.end(), [](auto& a, auto& b){ return a.second < b.second; });
    int count = 0, lastEnd = INT_MIN;
    for (auto& [s, e] : iv)
        if (s >= lastEnd) { count++; lastEnd = e; }
    return count;
}

, dominated by the sort.

Why earliest finish time

Greedy stays ahead: after picks, greedy’s -th interval finishes no later than the -th interval of any optimal solution, so greedy always has at least as much room left. See Exchange Arguments for the full proof.

The other sort keys are wrong

  • Earliest start — one very long interval blocks everything.
  • Shortest duration — a short interval in the middle can block two long ones.
  • Fewest conflicts — plausible, but constructible counterexamples exist.

Only earliest finish time is optimal.

The variants

ProblemMethodCost
Max count of non-overlappinggreedy by finish time
Min intervals to remove − the above
Max weight non-overlappingDP + binary search
Min rooms to host allinterval partitioning — max overlap
Max intervals with overlapping at oncegreedy + a min-heap of size
Cover a segment with the fewest intervalsgreedy: extend as far right as possible
non-overlapping sets, max totalmin-cost flow, or a DPvaries
Max non-overlapping on a circlefix one interval, then linear;

Minimum intervals to cover

sort(iv.begin(), iv.end());                               // by start
int cur = L, i = 0, cnt = 0;
while (cur < R) {
    int best = cur;
    while (i < n && iv[i].first <= cur) best = max(best, iv[i++].second);
    if (best == cur) return -1;                            // gap: impossible
    cur = best; cnt++;
}

Each step takes the interval reaching furthest right among those that start at or before the current position. The same “jump as far as possible” greedy solves the jump-game family.

Endpoints: open or closed?

Decide whether intervals touching at a point conflict:

  • Closed , touching conflicts → the condition is s > lastEnd.
  • Half-open , touching is fine → the condition is s >= lastEnd.

Read the statement. “A meeting ending at 3 and one starting at 3” is the standard ambiguity, and getting it backwards fails exactly one test.

QuestionMethod
Maximum simultaneous overlapsort / events, running maximum
Total covered lengthsort by start, merge overlapping
Points covered by the most intervalsthe same sweep
For each point, how many intervals cover itdifference array
Intervals containing a query pointoffline sweep + a set
Merge overlapping intervalssort by start, extend or emit
// maximum simultaneous overlap
vector<pair<int,int>> ev;
for (auto& [s, e] : iv) { ev.push_back({s, 1}); ev.push_back({e, -1}); }
sort(ev.begin(), ev.end());                                // -1 before +1 at equal times
int cur = 0, best = 0;
for (auto& [t, d] : ev) { cur += d; best = max(best, cur); }

The tie-break at equal times (-1 before +1) encodes the half-open convention — the same decision as above.

See also: Weighted Interval Scheduling · Interval Partitioning · Exchange Arguments