{x}
blog image

Minimum Number of Arrows to Burst Balloons

There are some spherical balloons taped onto a flat wall that represents the XY-plane. The balloons are represented as a 2D integer array points where points[i] = [xstart, xend] denotes a balloon whose horizontal diameter stretches between xstart and xend. You do not know the exact y-coordinates of the balloons.

Arrows can be shot up directly vertically (in the positive y-direction) from different points along the x-axis. A balloon with xstart and xend is burst by an arrow shot at x if xstart <= x <= xend. There is no limit to the number of arrows that can be shot. A shot arrow keeps traveling up infinitely, bursting any balloons in its path.

Given the array points, return the minimum number of arrows that must be shot to burst all balloons.

 

Example 1:

Input: points = [[10,16],[2,8],[1,6],[7,12]]
Output: 2
Explanation: The balloons can be burst by 2 arrows:
- Shoot an arrow at x = 6, bursting the balloons [2,8] and [1,6].
- Shoot an arrow at x = 11, bursting the balloons [10,16] and [7,12].

Example 2:

Input: points = [[1,2],[3,4],[5,6],[7,8]]
Output: 4
Explanation: One arrow needs to be shot for each balloon for a total of 4 arrows.

Example 3:

Input: points = [[1,2],[2,3],[3,4],[4,5]]
Output: 2
Explanation: The balloons can be burst by 2 arrows:
- Shoot an arrow at x = 2, bursting the balloons [1,2] and [2,3].
- Shoot an arrow at x = 4, bursting the balloons [3,4] and [4,5].

 

Constraints:

  • 1 <= points.length <= 105
  • points[i].length == 2
  • -231 <= xstart < xend <= 231 - 1

Minimum Number of Arrows to Burst Balloons

This problem asks for the minimum number of arrows needed to burst all balloons, given a list of balloon intervals. Each arrow shot vertically bursts all balloons whose intervals overlap the arrow's x-coordinate.

Approach

The optimal solution uses a greedy approach. The core idea is to sort the balloons by their end points (xend). Then, iteratively select the balloon with the smallest end point, and use an arrow to burst it and any other balloons that overlap with it. We then move to the next balloon that doesn't overlap with the shot arrow. This process continues until all balloons are burst.

Algorithm

  1. Sort: Sort the points array by the second element (xend) of each interval in ascending order.

  2. Initialization: Initialize ans (the count of arrows) to 0 and last (the rightmost point reached by arrows) to negative infinity.

  3. Iteration: Iterate through the sorted points array:

    • If the current balloon's start point (xstart) is greater than last, it means a new arrow is needed. Increment ans and update last to the current balloon's end point (xend).
    • Otherwise, the current balloon overlaps with an existing arrow, so no new arrow is needed.
  4. Return: Return ans.

Time and Space Complexity Analysis

  • Time Complexity: O(N log N), dominated by the sorting step. The iteration through the sorted array takes O(N) time.

  • Space Complexity: O(log N) (or O(N) depending on the sorting algorithm used). In-place sorting algorithms like quicksort or mergesort have O(log N) space complexity, while some others might have O(N) depending on implementation. The extra space used for ans and last is negligible.

Code Implementation (Python)

class Solution:
    def findMinArrowShots(self, points: List[List[int]]) -> int:
        if not points:
            return 0
 
        # Sort by end points
        points.sort(key=lambda x: x[1])
 
        arrows = 0
        last_end = float('-inf')  # Initialize last_end to negative infinity
 
        for start, end in points:
            if start > last_end:
                arrows += 1
                last_end = end
        return arrows

This Python code directly implements the algorithm described above. The lambda x: x[1] function is used as the key for sorting based on the second element of each sublist. The use of float('-inf') ensures that the first balloon will always trigger a new arrow.

Code Implementation (Java)

import java.util.Arrays;
import java.util.Comparator;
 
class Solution {
    public int findMinArrowShots(int[][] points) {
        if (points == null || points.length == 0) {
            return 0;
        }
 
        // Sort by end points using a custom comparator
        Arrays.sort(points, Comparator.comparingInt(a -> a[1]));
 
        int arrows = 0;
        long lastEnd = Long.MIN_VALUE; // Initialize lastEnd to a very small value
 
        for (int[] point : points) {
            if (point[0] > lastEnd) {
                arrows++;
                lastEnd = point[1];
            }
        }
        return arrows;
    }
}

The Java code mirrors the Python solution, using a custom Comparator for sorting and Long.MIN_VALUE for initialization to avoid potential overflow issues.

The other languages (C++, Go, TypeScript, C#) would follow a similar pattern, adapting the sorting and data structures to their specific syntax and libraries. The core algorithm remains the same across all languages.