leetcode 452. 用最少数量的箭引爆气球(贪心)

本文介绍了两种不同的算法思路来解决一个计算机科学中的问题:如何用最少数量的箭引爆所有气球。第一种方法是按气球左端点排序后遍历,更新最大覆盖范围;第二种方法则是按右端点排序,采用贪心策略。这两种方法都是为了找到覆盖所有气球的最小箭数。代码示例中详细展示了这两种实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

452. 用最少数量的箭引爆气球

一、题意

大体来说,就是有一堆气球,每个气球有不同的直径,把它们摆放在平面上,那从侧面来看,就是下边图片的形状:
在这里插入图片描述

对于每个气球,只给出其直径左右两边的 x 坐标值,其格式为[x1, x2]。现在给出一组坐标对,形如 points = [[10,16],[2,8],[1,6],[7,12]], 题目要求我们用从 x 轴下方(x=x0)处沿着 y 轴的正方向箭射,如何用最少的箭将气球全部射爆!射爆气球的条件是 x1 <= x0 <= x2

二、解题思路

按照每个气球的左端点从小到大排序,然后从左到右遍历,找到多个气球重合的最小区间,然后射一次箭,一直到遍历结束。

#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>

using namespace std;

class Solution {
private:
	// 传入的参数 a 和 b 如果是引用,可以在一定程度上提高运行的速度
    static bool cmp(const vector<int> &a, const vector<int> &b) {
        return a[0] < b[0];
    }
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        int size = points.size();
        if (size <= 1)
            return size;
            
        int count = 1; // 初始化值为1
        sort(points.begin(), points.end(), cmp);
        
        int num_0, num_1;
        int first_max = points[0][0];
        int end_min = points[0][1];
        // 这里避免在循环里多次调用数组,防止过多的IO,原理详见CSAPP
        for (int i = 1; i < size; i++) {
            num_0 = points[i][0];
            num_1 = points[i][1];
            if(num_0 >= first_max && num_0 <= end_min){
                first_max = first_max < num_0 ? num_0 : first_max;
                end_min = end_min > num_1 ? num_1 : end_min;
            }else{
                count++;
                first_max = num_0;
                end_min = num_1;
            }
        }
        return count;
    }
};


int main() {

    // vector<vector<int>> points = {{10,16},{2,8},{1,6},{7,12}};
    // vector<vector<int>> points = {{1,2},{3,4},{5,6},{7,8}};
    vector<vector<int>> points = {{1,2},{2,3},{3,4},{4,5}};
    // vector<vector<int>> points = {{1,2},{1,2}};
    Solution obj;
    int res = obj.findMinArrowShots(points);
    cout <<"result is :" << res << endl;
    system("pause");
    return 0;
}

在看过其他人的题解后,感觉这个方法很复杂。下边是另一种思路,按照右边端点排序:

class Solution {
    public int findMinArrowShots(int[][] points) {
        /**
        我特么射爆!!!!!!! \(^o^)/
        
        贪心法, 每个气球只少需要一支箭, 先按照右端点排序, 然后每次
        从最小的右端点射出一支箭, 去掉被射爆的气球, 重复该过程. 
        **/
        if(points.length < 1) return 0;
        Arrays.sort(points, (a, b) -> (a[1] - b[1]));
        int count = 1;
        int axis = points[0][1];
        
        for(int i = 1; i < points.length; ++i) {
            if(axis < points[i][0]) {
                count++;
                axis = points[i][1];
            }
        }
        
        return count;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhang L.R.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值