Minimum Number of Arrows to Burst Balloons

MediumIntervals · Greedy · Sorting🧩 Intervals & Line SweepLeetCode #452 ↗Updated

Problem

Each balloon spans a closed horizontal range points[i] = [xStart, xEnd]. An arrow shot vertically at x bursts every balloon with xStart ≤ x ≤ xEnd and keeps flying. Return the minimum number of arrows needed to burst all balloons.
Inputpoints = [[10,16],[2,8],[1,6],[7,12]]Output2
Inputpoints = [[1,2],[3,4],[5,6],[7,8]]Output4
Inputpoints = [[1,2],[2,3],[3,4],[4,5]]Output2

1 ≤ points.length ≤ 105  ·  -231 ≤ xStart ≤ xEnd ≤ 231-1

Try it yourself

Java
class Solution {
    public int findMinArrowShots(int[][] points) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Look at the balloon that ends first: some arrow must hit it, and shooting at its right edge hits it and as many others as possible. Sorting by end turns that into a single greedy pass.
PatternIntervals & Line Sweep

Instinct See [start, end] pairs, meetings, bookings or the word "overlap"? Sort by an endpoint, then sweep left to right carrying one running fact.

Memory hack Sort, then sweep - start time to merge, end time to choose, +1/-1 events to count the crowd.

Open the Intervals & Line Sweep guide →

Approaches

Brute ForceRepeated Earliest-End Scan (No Sorting)

Time O(n2)Space O(n)

While balloons remain, scan for the unburst balloon with the smallest end, shoot exactly there, and mark everything that arrow pierces. Each round costs O(n) and may remove only one balloon, so the total is quadratic.

Java
public int findMinArrowShots(int[][] points) {
    int n = points.length, left = n, arrows = 0;
    boolean[] burst = new boolean[n];
    while (left > 0) {
        int pick = -1; // unburst balloon that ends first
        for (int i = 0; i < n; i++) {
            if (!burst[i] && (pick == -1 || points[i][1] < points[pick][1])) pick = i;
        }
        int x = points[pick][1];
        arrows++;
        for (int i = 0; i < n; i++) {
            if (!burst[i] && points[i][0] <= x && x <= points[i][1]) {
                burst[i] = true;
                left--;
            }
        }
    }
    return arrows;
}

Captures the right greedy rule, but rescans the array every round.

At a glance

LevelApproachTimeSpace
Brute ForceRepeated Earliest-End Scan (No Sorting)O(n2)O(n)
BetterSort by Start, Shrink the Shared WindowO(n log n)O(log n)
OptimalSort by End, Shoot at Right EdgesO(n log n)O(log n)
Common pitfalls
  • Comparator a[1] - b[1] — overflows on extreme coordinates.
  • Using >= — touching balloons ([1,2],[2,3]) share one arrow.
  • Sorting by start but keeping the first balloon's end instead of the running minimum.
Interview tips
  • Argue the exchange: moving any arrow right up to the first end never loses a balloon.
  • Note the link to Non-overlapping Intervals: arrows = n − removals there.
  • Point out closed intervals here versus half-open ones in meeting problems.
Pattern
Interval stabbing, sort by end → fewest points that hit every interval.
My notes saved in this browser