如何快速区间合并?C++

区间合并的介绍:

给定一些区间,输出这些区间整体的区间范围。

比如:

        有区间 [ 1 , 2 ]  [ 1 , 3 ]  [ 2 , 4 ]  [ 5 , 6 ]  [ 6 , 8 ]

        那么合并后的区间就是 [ 1 , 4 ]  [ 5 , 8 ]

核心思想:

        将所有区间按 左边界 从小到大 排序

        用两个变量 l 和 r 维护当前区间,然后遍历整个排好序后的区间集合

        如果用 [ l , r ] 表示当前区间, [ a , b ] 表示下一个区间,则一共有下面三种情况:

                1、  a > r         说明两个区间没有交集,那就直接把 [ l , r ] 这个区间存入容器中。

                                        因为已经按左边界排序过了,后面的区间也不可能和 [ l , r ] 有交集。

                                        [ l , r ] 这个区间就是一个孤立的区间了。

                2、  a < r  且  b < r          说明 [ a , b ] 在 [ l , r ] 内,l 和 r 的值就不需要改变

                3、  a < r  且  b > r          说明两个区间有部分交集,合并后整个区间变长了,所以

                                                        r 的值需要变:r = b,整个区间变为:[ l , b ]

        其中,后面两种情况可以合在一起写: r = max ( r , b );

具体例子(一定要看):

题目:现输入 n 个区间 [ l , r ],输出合并后的区间。

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

using namespace std;

typedef pair<int, int> PII;  // 用 pair 存储区间

const int N = 100010, INF = 1e9;  // INF 是无穷大的意思
int n;
vector<PII> v;  // v 用来存储所有的区间

// 合并区间的主要操作
void merge(vector<PII>& v){
    
    vector<PII> res;  // res 存储合并后的区间
    
    sort(v.begin(), v.end());  // 按 “左边界” 从小到大排序
    
    int l = -INF, r = -INF;  // 初始让左右边界都为无穷小
    for (auto i : v){
        
        if (i.first > r){  // 说明 i 这个区间和当前的区间没有交集
            // 如果是第一个区间就不放入,不是第一个区间就放入
            if (l != -INF) 
                res.push_back({l, r});
            l = i.first, r = i.second;  // 更新当前区间
        }
        // 如果有交集,就让有边界取两者最远的那个
        else  r = max(r, i.second);
    }
    
    res.push_back({l, r});  // 最后一个区间需要手动放入
    
    v = res;  // 原来存储区间的 v = 新存储的区间
}

int main(){
    cin >> n;
    // 读入 n 个区间,全部放进容器 v 中
    while (n--){
        int l, r;
        cin >> l >> r;
        v.push_back({l, r});
    }
    
    merge(v);
    
    // 输出
    for (auto i : v)
        cout << i.first << ' ' << i.second << endl;
    
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值