---
# System prepended metadata

title: 452. Minimum Number of Arrows to Burst Ballons
tags: [leetcode, greedy, sorting]

---

# 資訊

:::info
- Question: 452. Minimum Number of Arrows to Burst Ballons
- From: Leetcode Daily Challenge 2024.03.18
- Difficulty: Medium
:::

---

# 目錄

:::info
[TOC]
:::

---

# 題目

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] = [x_start, x_end]` denotes a balloon whose horizontal diameter stretches between `x_start` and `x_end`. 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 `x1-start` and `x_end` is burst by an arrow shot at x if `x_start <= x <= x_end`. 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:
:::success
- 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:
:::success
- 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:
:::success
- 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:
:::success
- 1 <= `points.length` <= $10^5$
- `points[i].length` == 2
- $-2^{31}$ <= `x_start` < `x_end` <= $2^{31} - 1$
:::

---

# 解法

## 概念

Greedy 題，也是很常見的 overlapping 問題

概念就是先選一個點射過去，然後再從沒破的氣球繼續選，不過怎麼選這個點就很重要，也就是 greedy 的核心

不出意外我又不夠 greedy 了，一開始我依照氣球的開頭 (`x_start`) 做排序，然後每次射的位置都選第一個還沒破的氣球的尾巴，一路做下去，但會發現如果遇到 `[[1,10],[2,9],[3,8],[4,7],[5,6]]` 這種測資，我會依序射 `[10,9,8,7,6]` 這樣，但其實會發現如果我直接射 `5` 或 `6` 就結束了，所以後面我改成對氣球的尾巴 (`x_end`) 做排序，然後一樣每次射的位置都選第一個還沒破的氣球的尾巴，排序後結果就是 `[[5,6],[4,7],[3,8],[2,9],[1,10]`，而按照 algorithm 我就會直接射到 `6`的確更 greedy！

## 程式碼

```python=
class Solution:
    def findMinArrowShots(self, points: List[List[int]]) -> int:
        points.sort( key = lambda x:x[1])
        ans = 0
        curr = -1
        n = len( points )
        i = 0
        while i < n:
            curr = points[i][1]
            i += 1
            ans += 1
            while i < n:
                if curr >= points[i][0] and curr <= points[i][1]:
                    i += 1
                else:
                    break
        return ans
```

---

# 複雜度

## 時間複雜度

只少會走過整條 list，所以是 $O(n)$

![TimeComplexity20240318](https://hackmd.io/_uploads/HyikSGrRp.png =80%x)

## 空間複雜度

只有固定參數，所以是 $O(1)$

![SpaceComplexity20240318](https://hackmd.io/_uploads/BJDbrzSC6.png =80%x)
