【笔试】区间合并

 做笔试题遇到一道区间合并的题目,给定若干区间[1,2] [2,3] [4,5]合并有覆盖的区间,即为[1,3] [4,5]。经过在网上搜索类似题目,得到两种解题思路。类似题目是LeetCode上的56题目

思路1.如果区间的端点范围很小,比如在范围[0,9999]。可以开一个10000大小的bool数组,然后输入区间覆盖的范围都复制true。则最后遍历数组,连续的true数据即为一个区间。这种方法适用于区间范围小,区间的平均跨度不是很大。

思路2. 首先,按区间的左端点排序,然后比较left和right值。比如区间[1,3] [2,6] [8,10]

第一步:[1,3],赋值left=1 ,right = 3

第二步:区间[2,6]的2与right值比较,2<3,表示这两个区间连接在一起,判断6与right值的大小,决定新的right值

第三步:区间[8,10]的8比新的right6大,即出现新的区间,存储上一个left和right。赋值新的left和right

分析一下时间复杂度,排序的时候是O(NlogN),然后线性扫一遍是O(N),所以总的时间复杂度是O(NlogN),跟区间的跨度没关系,跟区间端点的覆盖范围也没一毛钱关系! 
只跟区间的个数有关系,而且还是很可以接受的一个复杂度(毕竟log N跟常数的区别不是很大)。

代码:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

typedef vector<pair<int, int> > RangeList;

RangeList cover(const RangeList& intervals) {
    int left = intervals[0].first, right = intervals[0].second;
    RangeList result;

    for (int i = 1; i < intervals.size(); ++i) {
        if (intervals[i].first > right) {  // 前面自成一个区间,那么就此分开
            result.push_back(make_pair(left, right));
            left = intervals[i].first;
            right = intervals[i].second;
        } else if (intervals[i].second > right) {
            right = intervals[i].second;
        }
    }
    result.push_back(make_pair(left, right));

    return result;
}

void display(const RangeList& intervals) {
    for (int i = 0; i < intervals.size(); ++i)
        cout << intervals[i].first << ' ' << intervals[i].second << endl;
    cout << endl;
}

int main() {
    RangeList intervals;
    int n, start, end;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> start >> end;
        intervals.push_back(make_pair(start, end));
    }
    sort(intervals.begin(), intervals.end()); //对输入的区间排序
    RangeList result = cover(intervals);
    display(result);

    return 0;
}

代码中用到一个定义方式是vector<pair<int, int> >,以前没有使用过,特地查询了一下。

使用pair对,在vector中插入成对的数据

声明vector:

vector<pair<int,int> >vec

往vector中插入数据,需要用到make_pair:

vec.push_back(make_pair<int,int>(10,50));

vec.push_back(make_pair(20,30));

定义迭代器:

  vector<pair<int,int> > ::iterator iter;

for(iter=vec.begin();iter!=vec.end();iter++);

数据读取:

第一个数据:(*iter).first

第二个数据:(*iter).second

vector<pair<int,int> > vec中数据进行排序。直接使用sort(vec.begin(),vec.end())根据vec的first数组升序排序的。也可以根据vec的second进行排序。也可以控制排序方式为升序或者降序。

#include "stdafx.h"
#include <iostream>
#include <vector>
#include<algorithm>

using namespace std;

//根据first的值升序排序
bool cmp1(pair<int,int>a,pair<int,int>b)
{
    return a.first < b.first;  //a.first > b.first降序
}

//根据second的值升序排序
bool cmp2(pair<int, int>a, pair<int, int>b)
{
    return a.second < b.second;
}
int main()
{
    vector<pair<int, int>>vec;
    vec.push_back({ 1,2 });
    vec.push_back({ 4,2 });
    vec.push_back({ 3,3 });
    vec.push_back({ 2,1 });
    sort(vec.begin(), vec.end(), cmp1);
    cout << "根据first的值升序排序:" << endl;
    for (auto it = vec.begin();it != vec.end();it++)
    {
        cout << "(" << it->first << "," << it->second << ")" << endl;
    }
    sort(vec.begin(), vec.end(), cmp2);
    cout << "根据second的值升序排序:" << endl;
    for (auto it = vec.begin();it != vec.end();it++)
    {
        cout << "(" << it->first << "," << it->second << ")" << endl;
    }
}

猜你喜欢

转载自blog.csdn.net/csdn_chuxuezhe/article/details/81606837
今日推荐