Minimum Number of Arrows to Burst Balloons — Solution
Minimum Number of Arrows to Burst Balloons solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript.
Minimum Number of Arrows to Burst Balloons is a medium coding problem on arrays, sorting and greedy.
- Difficulty: Medium
- Topics: Arrays, Sorting, Greedy, Intervals
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
Balloons are horizontal segments points[i] = [xstart, xend]. An arrow shot vertically at x bursts every balloon with xstart <= x <= xend.
Return the minimum number of arrows to burst all balloons.
Example 1
Input: points = [[10,16],[2,8],[1,6],[7,12]]
Output: 2
Explanation: Arrows at x=6 and x=11.
Example 2
Input: points = [[1,2],[3,4],[5,6],[7,8]]
Output: 4
Constraints
1 <= points.length <= 20-100 <= xstart <= xend <= 100
Hints for Minimum Number of Arrows to Burst Balloons
Hint 1
Sort by right end; shoot at the first balloon's right edge.
Hint 2
That arrow bursts every balloon starting before it — repeat for the rest.
How to solve Minimum Number of Arrows to Burst Balloons
Exactly the activity-selection greedy again, wearing a different costume. Sort the balloons by their right edge and shoot at the first balloon's right edge — that arrow is as far right as it can be while still bursting that balloon, so it sweeps up as many others as possible. Skip everything it hits and repeat.
Approach
- Sort the balloons by
xend. - Shoot the first arrow at the first balloon's
xendand count it. - Walk the rest: any balloon whose
xstartis at or before the current arrow position is already burst — skip it. - The first balloon starting after the arrow needs a new one: shoot at its
xendand count again. - Return the number of arrows.
Why it works
The first balloon to end must be burst by some arrow, and that arrow cannot be positioned further right than its xend. Placing it exactly there is therefore optimal: any valid arrow for that balloon is at a position <= xend, so it bursts a subset of what the rightmost placement bursts. Removing all balloons hit leaves a smaller instance of the identical problem, so induction gives optimality.
Complexity
- Time —
O(n log n) - Space —
O(1)
Pitfalls
- Sort by the right edge. Sorting by the left edge breaks the argument and over-counts.
- A balloon touching the arrow exactly at its edge is burst, so the skip test is
xstart <= arrowX. - Compare against the current arrow's position, not the previous balloon's end.
- Coordinates can be negative; initialise the arrow position from the first balloon rather than from zero.
Reference solution
Python
from typing import List
def findMinArrowShots(points: List[List[int]]) -> int:
s = sorted(points, key=lambda p: p[1])
arrows = 0
x = float("-inf")
for st, en in s:
if st > x:
arrows += 1
x = en
return arrowsJava
public static int findMinArrowShots(int[][] points) {
int[][] s = points.clone();
Arrays.sort(s, (a, b) -> Integer.compare(a[1], b[1]));
int arrows = 0;
int arrowX = 0;
for (int[] p : s) {
if (arrows == 0 || p[0] > arrowX) {
arrows++;
arrowX = p[1];
}
}
return arrows;
}C++
int findMinArrowShots(vector<vector<int>>& points) {
vector<vector<int>> s = points;
sort(s.begin(), s.end(), [](const vector<int>& a, const vector<int>& b) { return a[1] < b[1]; });
int arrows = 0;
int arrowX = 0;
for (const auto& p : s) {
if (arrows == 0 || p[0] > arrowX) {
arrows++;
arrowX = p[1];
}
}
return arrows;
}JavaScript
var findMinArrowShots = function(points) {
const s = points.slice().sort(function(a, b) { return a[1] - b[1]; });
let arrows = 0, x = -Infinity;
for (const p of s) {
if (p[0] > x) {
arrows++;
x = p[1];
}
}
return arrows;
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 1199 arrays problems · the whole catalogue
Learn the technique: Arrays · Sorting Algorithms