• LintCode 30插入区间


    问题

    给出一个无重叠的按照区间起始端点排序的区间列表。

    在列表中插入一个新的区间,你要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

    样例

    插入区间[2, 5]  [[1,2], [5,9]],我们得到 [[1,9]]

    插入区间[3, 4]  [[1,2], [5,9]],我们得到 [[1,2], [3,4], [5,9]]

    思路

    只要依次遍历,判断当前元素与要插入元素的关系。

    如当前元素的右端点小于插入元素的左端点,则说明当前元素与插入元素无交并。

    如当前元素的左端点大于插入元素的右端点,也说明当前元素与插入元素无交并。

    依次遍历,判断当前元素与要插入元素的关系,若newInterval.end<it->start,则找到了插入点,插入这个新区间

    若是相交的,那么就停止比较,把要插入元素和当前元素合并成新区间

    因为合并后的新区间也许和右边的元素有交集,会引起连锁反应,所以一直和右边的元素合并,直到无法合并为止

    使用链表做存储结构,插入删除十分快捷,要不是lintcode 一定要求用vector存储,使用list,会很省空间,都在原地插入合并

    代码

    #include<iostream>

    #include<vector>

    #include<list>

    #include <fstream>

    using namespace std;

    //LintCode 30

    //只要依次遍历,判断当前元素与要插入元素的关系。

    //如当前元素的右端点小于插入元素的左端点,则说明当前元素与插入元素无交并。

    //如当前元素的左端点大于插入元素的右端点,也说明当前元素与插入元素无交并。

    //依次遍历,判断当前元素与要插入元素的关系,若newInterval.end<it->start,则找到了插入点,插入这个新区间

    //若是相交的,那么就停止比较,把要插入元素和当前元素合并成新区间

    //因为合并后的新区间也许和右边的元素有交集,会引起连锁反应,所以一直和右边的元素合并,直到无法合并为止

    //使用链表做存储结构,插入删除十分快捷,要不是lintcode 一定要求用vector存储,使用list,会很省空间,都在原地插入合并

    //最开始我在想怎么能一次性合并上,不仅要考虑和左边区间的合并还要考虑和右边区间的合并,按照新的做法,我

    //只要考虑和右边区间的合并即可

    class Interval

    {

        public:

            int start, end;

            Interval(int start, int end)

            {

                this->start = start;

                this->end = end;

            }

    };

    vector<Interval> insert(vector<Interval> &intervals, Interval newInterval)

    {

        // write your code here

        list<Interval> myList(intervals.begin(), intervals.end());

        list<Interval>::iterator it;

        for (it=myList.begin(); it!=myList.end(); it++)

        {

            if(newInterval.end<it->start)

            //找到了插入点,插入点左边的区间是不可能和newInterval合并的,

            //因为插入点左边的区间先扫描,要是可以合并的话就跳出了这个循环

            {

                myList.insert(it,newInterval);

                vector<Interval> answer(myList.begin(),myList.end());

                return answer;

            }

            if(!(newInterval.start>it->end||newInterval.end<it->start))//找到了可以合并的区间

                break;

        }

        if(it==myList.end())//如果都不可以合并,而且插入点是最后一个区间之后

        {

            myList.push_back(newInterval);

            vector<Interval> answer(myList.begin(),myList.end());

            return answer;

        }

        //在it处与newInterval合并

        int start=(it->start<newInterval.start)?it->start:newInterval.start;

        int end=(it->end>newInterval.end)?it->end:newInterval.end;

        it->start=start;

        it->end=end;

        list<Interval>::iterator it2=++it;//迭代器只能++,--不能-1只好出此下策

        it--;

        //连锁反应不停地合并,直到不能合并为止,it2是it的下一个位置,如果已经到了end无需合并

        while(it2!=myList.end())

        {

            if(it->end<it2->start)//一旦无法继续合并,就跳出循环

                break;

            else//it需要与it+1合并

            {

                int end=(it->end>it2->end)?it->end:it2->end;

                it->end=end;

                it2=myList.erase(it2);//删除被合并的元素

            }

        }

        vector<Interval> answer(myList.begin(),myList.end());

        return answer;

    }

    int main()

    {

        ifstream in("LintCode30.txt");

        Interval newInterval(24,33);

        int num=0;

        int startp=0;

        int endp=0;

        in>>num;

        vector<Interval> intervals;

        for(int i=0; i<num; i++)

        {

            in>>startp>>endp;

            Interval tmp(startp,endp);

            intervals.push_back(tmp);

        }

        vector<Interval> answer=insert(intervals,newInterval);

        vector<Interval>::iterator it2;

        for (it2=answer.begin(); it2!=answer.end(); ++it2)

            cout<<it2->start<<" "<<it2->end<<endl;

    }

  • 相关阅读:
    繁忙的都市 最小生成树 入门题
    洛谷P2801 教主的魔法 分块
    洛谷 P3203 [HNOI2010]弹飞绵羊 分块
    洛谷P2607 [ZJOI2008]骑士 基环树动归
    Hdu 2586 树链剖分求LCA
    洛谷 P3384 【模板】树链剖分
    洛谷P1816 忠诚 分块
    最全前端开发面试问题及答案整理
    CSS垂直居中和水平居中
    实现一个图片懒加载插件有多难?
  • 原文地址:https://www.cnblogs.com/unflynaomi/p/8169099.html
Copyright © 2020-2023  润新知