C++ 区间合并 算法(详解) + 例题

1、定义

  • 把所有,有交集的区间合并

  • 图解:

      

2、实现

  • 步骤如下:
    • 1、首先按照每个区间左端点排序

    • 2、扫描 所有区间,进行区间合并

    • 上述第二条,可以理解为:拿出一个区间去跟它后面的所有的区间去进行合并(因为我们先拿出左端点去排序,所以不用害怕后面的区间会小于什么的)。

  • 图解:

      

· 代码模板: 

//将所有存在交集的区间进行合并
void merge(vector<PII> &segs)
{
    vector<PII> res;
    sort(segs.begin(),segs.end());
    int st = -2e9,ed = -2e9;
    for(auto seg : segs)
    {
        if(ed < seg.first)
        {
            if(st!=-2e9) res.push_back({st,ed});
            st = seg.first,ed = seg.second;
        }
        else ed = max(ed,seg.second);
    }
    if(st!=-2e9) res.push_back({st,ed});
    segs = res;
}

3、例题:803. 区间合并 - AcWing题库

  • 给定 n个区间 [li ri],要求合并所有有交集的区间。

    注意如果在端点处相交,也算有交集。

    输出合并完成后的区间个数。

    例如: [1,3] 和 [2,6] 可以合并为一个区间 [1,6]。

    输入格式

    第一行包含整数 n。

    接下来 n 行,每行包含两个整数 l 和 r。

    输出格式

    共一行,包含一个整数,表示合并区间完成后的区间个数。

    数据范围

    1≤n≤100000      −10 ^ 9 ≤ li ≤ ri ≤ 10 ^ 9

  • 输入样例:
    5
    1 2
    2 4
    5 6
    7 8
    7 9
    输出样例:
    3

    图解:

        

AC代码(这里给出两种写法): 

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


using namespace std;
typedef pair<int,int> PII;
const int N = 100010;
vector<PII> segs;
int n;

//区间合并
void merge(vector<PII> &segs)
{
    vector<PII> res;//用来存储
    //按区间的左端点来进行排序,然后再按照第二个排序(pair很像)
    sort(segs.begin(),segs.end());
    将st(start)和ed(end)初始化为负无穷,确保端点一定在左面
    int st = -2e9, ed = -2e9;
    for(auto seg : segs)
    {
        //如果比较区间的左端点不在当前区间中
        if(ed < seg.first)
        {
            //判断一下是否更新 新的当前区间(以防第一次更新)
            if(st!=-2e9) res.push_back({st,ed});
            st = seg.first,ed = seg.second;//更新区间,变成当前区间
        }
        //如果比较区间的左端点在区间中更新一下最大的右端点
        else ed = max(ed,seg.second); 
    }
    //看一下,最后一个元素是否被合并
    if(st!=-2e9) res.push_back({st,ed});
    
    segs = res;
}

int main()
{
    cin >> n;
    //存入坐标
    for(int i=0;i<n;i++)
    {
        int l,r;
        cin >> l >> r;
        segs.push_back({l,r});
    }
    //区间合并
    merge(segs);
    
    cout << segs.size() << endl;
    return 0;
}
第二种: 
#include<bits/stdc++.h>

using namespace std;
typedef pair<int, int> PII;
vector<PII> segs;
int n,res;

int main()
{
    cin >> n;
    for(int i=0;i<n;i++)
    {
        int l,r;
        cin >> l >> r;
        segs.push_back({l,r});
    }
    
    sort(segs.begin(),segs.end());
    int ed = segs[0].second;
    for(int i=1;i<n;i++)
    {
        if(ed < segs[i].first)
        {
            res++;
            ed = segs[i].second;
        }
        else ed = max(ed,segs[i].second);
    }
    
    cout << res + 1 << endl;
    return 0;
}

  • 26
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值