[Algorithm][贪心][合并区间][无重叠区间][用最少数量的箭引爆气球]详细讲解


1.合并区间

1.题目链接


2.算法原理详解

  • 区间问题思路
    • 排序
      • 左端点(本题)
      • 右端点
    • 根据排序后的结果,总结规律
  • 解法:排序(左端点) + 贪心
    • 性质能够合并的区间,都是连续的
    • 如何合并?
      • 求并集
        请添加图片描述

3.代码实现

vector<vector<int>> merge(vector<vector<int>>& intervals) 
{
    // 排序
    sort(intervals.begin(), intervals.end());

    // 合并区间
    vector<vector<int>> ret;
    int left = intervals[0][0], right = intervals[0][1];

    for(int i = 0; i < intervals.size(); i++)
    {
        int a = intervals[i][0], b = intervals[i][1];
        if(a <= right) // 有重叠
        {
            right = max(right, b);
        }
        else // 无重叠
        {
            ret.push_back({left, right});
            left = a;
            right = b;
        }
    }

    // 最后一个区间
    ret.push_back({left, right});

    return ret;
}

2.无重叠区间

1.题目链接


2.算法原理详解

  • 解法:排序(左端点) + 贪心
  • 问题转化:移除最少区间 <–> 保留更多区间
    • 优先干掉右端点长的区间 --> 长的区间更后续区间重叠的概率更大
      请添加图片描述

3.代码实现

int eraseOverlapIntervals(vector<vector<int>>& intervals) 
{
    // 排序
    sort(intervals.begin(), intervals.end());

    // 移除区间
    int ret = 0;
    int left = intervals[0][0], right = intervals[0][1];
    for(int i = 1; i < intervals.size(); i++)
    {
        int a = intervals[i][0], b = intervals[i][1];
        if(a < right) // 有重叠
        {
            ret++; // DELETE
            right = min(right, b); // 贪心, 删除右端点较大的区间
        }
        else // 无重叠
        {
            right = b;
        }
    }

    return ret;
}

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

1.题目链接


2.算法原理详解

  • 问题抽象:区间问题
  • 问题转化:最少的弓箭数量 --> 一只箭应该引爆更多的气球 --> 将互相重叠的所有区间都拿出来引爆
  • 解法:排序(左端点) + 贪心
    • 性质:按照左端点排序之后,互相重叠的区间是连续的(约束更强)
    • 如何合并?
      • 求交集
        请添加图片描述

3.代码实现

int findMinArrowShots(vector<vector<int>>& points) 
{
    // 排序
    sort(points.begin(), points.end());

    // 求互相重叠区间的数量
    int right = points[0][1];
    int ret = 1;
    for(int i = 1; i < points.size(); i++)
    {
        int a = points[i][0], b = points[i][1];
        if(a <= right) // 有重叠
        {
            right = min(right, b);
        }
        else // 无重叠
        {
            ret++;
            right = b;
        }
    }

    return ret;
}
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DieSnowK

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

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

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

打赏作者

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

抵扣说明:

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

余额充值