用最少数量的箭引爆气球

该博客探讨了一个优化问题:如何用最少数量的箭引爆所有气球。通过将箭移动到引爆气球的最左边界,可以保持解决方案的最优性。博主提出了一种策略,即从最左侧的气球开始,每次选择一个箭能引爆的最左侧剩余气球,直到所有气球都被引爆。此问题等价于寻找区间交集的合并。
摘要由CSDN通过智能技术生成

fig1

这是为什么?我们考虑任意一种最优的方法,对于其中的任意一支箭,我们都通过上面描述的方法,将这支箭的位置移动到它对应的「原本引爆的气球中最靠左的右边界位置」,那么这些原本引爆的气球仍然被引爆。这样一来,所有的气球仍然都会被引爆,并且每一支箭的射出位置都恰好位于某一个气球的右边界了。

有了这样一个有用的断定,我们就可以快速得到一种最优的方法了。考虑所有气球中右边界位置最靠左的那一个,那么一定有一支箭的射出位置就是它的右边界(否则就没有箭可以将其引爆了)。当我们确定了一支箭之后,我们就可以将这支箭引爆的所有气球移除,并从剩下未被引爆的气球中,再选择右边界位置最靠左的那一个,确定下一支箭,直到所有的气球都被引爆。)
 

按左端右端排序都是一样的,都是寻求最小交集区间。[0,9]和[0,6]交集[0,6],所以[0,6]上可以一箭射穿,[0,6]和[7,8]没有交集,所以箭数+1

题目等价: 求交集的合并区间

class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
    //合并区间
    sort(begin(points),end(points),[](vector<int>&pos1,vector<int>& pos2){
        return pos1[0]<pos2[0];
    });
    vector<vector<int> >  merged;
    merge(points,merged);
    return merged.size();
    }
    //
    void merge(vector<vector<int> >& intervals,vector<vector<int> >&res)
    {
     for(auto& interval:intervals){
         int i=interval[0];//左边界
         int j=interval[1];//右边界
         // [1,2],[3,4] -> [1,2],[3,4]
         if(res.empty()||res.back()[1]<i) res.push_back({i,j});
         else{
         //[1,5],[2,4] -> [2,4]  [1,5],[2,6] -> [2,5]
             res.back()[0]=max(res.back()[0],i);//左边取小的
             res.back()[1]=min(res.back()[1],j);
         }
     }
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值