Javascript 间隔范围插入并拆分为唯一范围

Javascript 间隔范围插入并拆分为唯一范围,javascript,algorithm,language-agnostic,pseudocode,Javascript,Algorithm,Language Agnostic,Pseudocode,寻找算法思想如何插入区间范围值,使其不会与现有区间重叠 区间范围从最小到较大排序 现在插入区间范围[0,7]到[[0,1],[3,5]->[[0,1],[1,3],[3,5],[5,7]->生成了两个新区间,其他区间保持不变 这里是另一个例子,插入范围[-3,5]到[[0,1],[6,7]->[-3,0],[0,1],[1,5],[6,7]] 所有编程语言(特别是JavaScript)也都欢迎伪代码实现 在实际代码中,在应用某些操作后,旧的间隔范围和新的范围之间存在差异。这些范围将合并在一起。我

寻找算法思想如何插入区间范围值,使其不会与现有区间重叠

区间范围从最小到较大排序

现在插入区间范围[0,7]到[[0,1],[3,5]->[[0,1],[1,3],[3,5],[5,7]->生成了两个新区间,其他区间保持不变

这里是另一个例子,插入范围[-3,5]到[[0,1],[6,7]->[-3,0],[0,1],[1,5],[6,7]]

所有编程语言(特别是JavaScript)也都欢迎伪代码实现

在实际代码中,在应用某些操作后,旧的间隔范围和新的范围之间存在差异。这些范围将合并在一起。我想把问题分成更小的部分,这样合并的部分就被忽略了

单独:更容易直接在新区间中合并,而不是人为地将其拆分。以下是我的建议(C++):

使用数据类型=/*任何适当的;双精度,整数,无符号整数,*/;
使用Interval=std::pair;
std::向量间隔;
空白插入(间隔x)
{
if(interval.empty()| | x.secondinterval.back().second)
{
间隔。推回(x);/(2)
}
其他的
{
自动b=间隔。开始();
而(b->second第一次)
{
//这是std::prev(b)和(b)之间的新间隔
间隔。插入(b,x);
}
其他的
{
//b与x重叠!
如果(b->first>x.first)
{
b->first=x.first;
}
自动e=标准::下一个(b);
而(e!=interval.end()&&e->first second=std::max(x.second,l->second);
//删除现在包含在b中的所有后续间隔(可能没有)
擦除间隔(标准::下一步(b),e);
}
}
}
仅限算法,省去了打包到类中的设计工作,具有接受开始/结束标记(而不是间隔)的方便函数


如果您打算使用的数据类型不提供回溯访问器(C++:例如
std::forward\u list
):没问题,如果
(包含
(2)
,只需删除第二个
);然而,
b
可以作为结束迭代器,因此您必须进行测试,如果测试成功,您可以在结束时插入。您很可能没有“之前插入”,因此您也需要分别跟踪b和之后的e的前辈…

我们不能为您选择语言。我添加了JavaScript标记,但任何C都一样(php、java、c#和python)也欢迎使用伪代码。您想要“更好”的算法,但还没有发布自己的算法…这在codereview或codegolf中会更好。语言为什么重要?算法没有特定语言的标记非常清楚地表明OP想要一个算法:解决问题的路线图。他没有要求具体的实现。
using DataType = /* whatever appropriate; double, int, unsigned int, ...*/;
using Interval = std::pair<DataType, DataType>;
std::vector<Interval> intervals;

void insert(Interval x)
{
    if(intervals.empty() || x.second < intervals.front().first)
    {
        intervals.insert(intervals.begin(), x); // (1)
    }
    else if(x.first > intervals.back().second)
    {
        intervals.push_back(x); // (2)
    }
    else
    {
        auto b = intervals.begin();
        while(b->second < x.first)
        {
            std::advance(b, 1);
        }
        // cannot be END iterator, otherwise would have been caught by (2)
        if(x.second < b->first)
        {
            // this is a new interval in between std::prev(b) and (b)
            intervals.insert(b, x);
        }
        else
        {
            // b is overlapping with x!
            if(b->first > x.first)
            {
                b->first = x.first;
            }

            auto e = std::next(b);
            while(e != intervals.end() && e->first <= x.second)
            {
                std::advance(e, 1);
            }
            // e is the first interval NOT overlapping with x!
            auto l = std::prev(e);
            b->second = std::max(x.second, l->second);
            // drop all subsequent intervals now contained in b (possibly none)
            intervals.erase(std::next(b), e);
        }
    }
}