We have a collection of intervals, and we need to pick a set of integers such that every interval contains at least two of our chosen integers. The goal is to make this set as small as possible.
A useful way to frame it is placing pins on a number line. Each interval demands at least two pins inside it, and we want the fewest pins total. A single pin can serve several overlapping intervals at once, so placement matters. A pin near the right end of an interval is more reusable than one near the left, because intervals that we still have to handle tend to sit further to the right.
This leads to the strategy used below: process intervals in order of their right endpoint, and when an interval needs more pins, place them as far right as it allows. An interval that ends early is the most constrained, so handling it first and reusing its pins for later, wider intervals keeps the total small.
1 <= intervals.length <= 3000. With n up to 3000, an O(n^2) solution still runs in about 9 million operations and passes, but sorting plus one pass gives O(n log n).0 <= start_i < end_i <= 10^8. The value range is too large for a boolean array indexed by value. The algorithm has to work with interval endpoints, not iterate over every possible integer.Consider every possible set of integers and find the smallest one that satisfies the constraint. The candidates can be limited to integers that appear in at least one interval, since no other value helps. For each subset of those candidates, in increasing order of size, check whether every interval contains at least two elements from it, and return the first size that works.
This is impractical as a real solution. The value range goes up to 10^8, and even restricting to integers within intervals leaves an enormous search space. It does establish what kind of problem this is: a minimum set cover variant where each interval is a constraint that two chosen values must satisfy.
Loading animation...
Enumerating subsets is hopeless at this scale. The next approach processes intervals in a fixed order and decides greedily which numbers to pick, which removes the exponential search entirely.
Intervals that end earliest are the most constrained. An interval ending at position 5 must hold two chosen numbers, all of which are at most 5. An interval ending at position 100 has far more room. Sorting by right endpoint handles the tight intervals first, while their right endpoints are still small.
Process intervals in that order. For each one, count how many already-chosen numbers fall inside it. If two or more do, it is satisfied and we move on. If one does, we add one number. If none do, we add two.
New numbers go as far right as the current interval allows. Because intervals are sorted by right endpoint, every interval still to come ends at this position or later, so a number placed at the right end of the current interval is the one most likely to also fall inside those later intervals.
Ties in the right endpoint are broken by larger left endpoint first, processing the narrower interval before the wider one with the same end. Any number that satisfies the narrower interval lies inside the wider one as well, so this ordering never wastes a pin.
Tracking only the two largest chosen numbers p1 and p2 is enough. The chosen numbers only ever grow, so the two largest are also the two most likely to land inside an interval whose right endpoint is the current one or larger. If p1 and p2 both fall short of an interval, no smaller chosen number can be inside it either.
Placing new numbers at end (and end - 1 when two are needed) is safe because every later interval has right endpoint >= end, so a value at end is never wasted on an interval that has already been processed and always remains a candidate for the ones ahead.
p1 and p2, where p1 < p2). Initialize both to -1.[start, end]:start <= p1, both p1 and p2 are inside this interval. Skip.start <= p2, only p2 is inside. Add end. Update: p1 = p2, p2 = end. Increment count by 1.end - 1 and end. Update: p1 = end - 1, p2 = end. Increment count by 2.Loading animation...
p1 and p2 regardless of input size.This approach is optimal for the "at least two" requirement. The two-variable trick is specific to the number two. A version that asks for at least k elements per interval needs a different bookkeeping scheme, which the next approach provides.
This uses the same sort order but keeps an explicit sorted list of every chosen number instead of two variables. For each interval, two binary searches count how many chosen numbers fall inside it. If fewer than two do, the missing numbers are inserted at the rightmost positions the interval allows.
The benefit is generalization: replacing the constant 2 with k solves the "at least k" version with no other change, because the count-and-fill logic does not depend on the target being two. The cost is a higher running time, since inserting into a sorted array shifts elements and can take O(n) per insertion.
chosen of all selected numbers.[start, end]:chosen fall in [start, end].end to chosen (if not already present).end - 1 and end to chosen.chosen.Loading animation...
chosen list. In the worst case (all intervals are disjoint), we store 2n numbers.