Minimum Number of Arrows to Burst Balloons
Problem
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.points = [[10,16],[2,8],[1,6],[7,12]]Output2points = [[1,2],[3,4],[5,6],[7,8]]Output4points = [[1,2],[2,3],[3,4],[4,5]]Output21 ≤ points.length ≤ 105 · -231 ≤ xStart ≤ xEnd ≤ 231-1
Try it yourself
class Solution {
public int findMinArrowShots(int[][] points) {
}
}
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)
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.
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.
BetterSort by Start, Shrink the Shared Window
O(n log n)Space O(log n)Sort by start and grow a group of balloons that one arrow can still hit. The group's shootable window ends at the minimum end seen so far; a new balloon that starts after that point can't join, so a new arrow begins.
public int findMinArrowShots(int[][] points) { Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0])); int arrows = 1; int windowEnd = points[0][1]; // last x that hits the whole group for (int i = 1; i < points.length; i++) { if (points[i][0] > windowEnd) { arrows++; // can't share: start a new group windowEnd = points[i][1]; } else { windowEnd = Math.min(windowEnd, points[i][1]); } } return arrows; }
Fast, but must track a shrinking window — easy to forget the min.
OptimalSort by End, Shoot at Right Edges
O(n log n)Space O(log n)Sort by end. Fire the first arrow at the first balloon's end. Every later balloon that starts at or before that arrow is already burst (its end is ≥ the arrow); the first one that starts after it needs a new arrow at its end.
public int findMinArrowShots(int[][] points) { // Integer.compare avoids overflow on values near the int limits Arrays.sort(points, (a, b) -> Integer.compare(a[1], b[1])); int arrows = 1; int arrowX = points[0][1]; for (int[] p : points) { if (p[0] > arrowX) { // this balloon is past the last arrow arrows++; arrowX = p[1]; } } return arrows; }
Dry runpoints = [[10,16],[2,8],[1,6],[7,12]]
- sorted1-62-87-1210-16by end
- i=01-6a2-87-1210-16arrow at 6, arrows=1
- i=11-6a2-87-1210-162 ≤ 6: burst
- i=21-62-87-12a10-167 > 6: arrow at 12
- i=31-62-87-12a10-1610 ≤ 12: burst ✔
Same Big-O as Better with less state — the canonical greedy.
a[1] - b[1]: with coordinates near
±231 the subtraction overflows and corrupts the order.At a glance
| Level | Approach | Time | Space |
|---|---|---|---|
| Brute Force | Repeated Earliest-End Scan (No Sorting) | O(n2) | O(n) |
| Better | Sort by Start, Shrink the Shared Window | O(n log n) | O(log n) |
| Optimal | Sort by End, Shoot at Right Edges | O(n log n) | O(log n) |
- 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.
- 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.