简体   繁体   English

使用Binary Search将Interval插入不相交的间隔中

[英]Insert Interval into a disjoint set of intervals with Binary Search

Given 给定

class Interval{
   int start;
   int end;
}

Task is to insert an Interval into a disjoint set or list of Intervals. 任务是将一个间隔插入到不相交的集合或间隔列表中。 So for example 所以举个例子

<4,8> into <3,7><10,13><20,21><30,31><40,45> gives <3,8><10,13><20,21><30,31><40,45>

<1,30> into <3,7><10,13><20,21><30,31><40,45> gives <1,30><40,45>

and etc.

I know we should use 2 binary searches for the most efficient solution and that we should be comparing the inserted interval's start with the list intervals' end and vice versa. 我知道我们应该使用2个二进制搜索来找到最有效的解决方案,并且我们应该比较插入间隔的开始与列表间隔的结束,反之亦然。 How exactly do we handle binary search when we can't find exactly what we're looking for? 当我们找不到确切要寻找的东西时,我们如何处理二进制搜索?

Count the number of nodes. 计算节点数。 Go back to the centre, insert if applicable. 返回中心,如果适用,插入。 Otherwise decide which half of the list is of interest. 否则,确定列表中的哪一半是您感兴趣的。 Go back to it's centre, insert etc. You need to handle the exception <4 9> into <2 5> <8 12>. 返回其中心,插入等。您需要将异常<4 9>放入<2 5> <8 12>中。

Assuming C++, I'd use an std::map from the interval end to the interval start. 假设使用C ++,我将使用std::map从间隔结束到间隔开始。 For searching, use std::upper_bound() to find the first overlapping interval and then advance the iterator to find all overlapping intervals. 对于搜索,请使用std::upper_bound()查找第一个重叠间隔,然后使迭代器前进以查找所有重叠间隔。 Only one binary search is required. 只需要一个二进制搜索。

#include <map>
#include <stdio.h>

typedef std::map<int, int> IntervalMap;

struct Interval {
    int start;
    int end;
};

int main()
{
    IntervalMap imap;
    Interval query;

    imap[7] = 3;    // <3,7>
    imap[13] = 10;  // <10,13>

    // Insert: <4,8>
    query.start = 4;
    query.end = 8;

    // Find the first overlapping interval
    auto it = imap.upper_bound(query.start);
    if (it != imap.end() && it->second < query.end)
    {
        // There is one or more overlapping interval
        // Update lower bound for the new interval
        if (it->second < query.start)
            query.start = it->second;

        while (it != imap.end() && it->second < query.end)
        {
            // Update upper bound for the new interval
            if (it->first > query.end)
                query.end = it->first;

            auto tmp = it;
            ++it;
            imap.erase(tmp);
        }
    }

    // Insert the new interval
    imap[query.end] = query.start;

    for (auto it = imap.begin(); it != imap.end(); ++it)
    {
        fprintf(stderr, "<%d,%d>\n", it->second, it->first);
    }

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM