在重叠区间中查找基本区间
我在准备一些编程面试时遇到了一个很好的问题。
给定一组可能重叠的区间,您需要编写一个函数来返回其中的所有基本区间。例如:如果给定的间隔为以下对列表:{{1,5}、{3,10}、{5,11}、{15,18}、{16,20}},那么您需要返回以下内容:
{1,3}, {3,5}, {5,10}, {10,11}, {15,16}, {16,18}, {18,20}}
{ 跟随在上面的答案:
- 答案中省略了区间{11,15},因为它是 输入中不存在。
- 输入的区间 {1,5} 已分为 {1,3}、{3,5} 在答案中,因为在 {3,10} 中定义了起点“3” 将区间分割为两个基本区间的输入。
Java 中的方法签名:
List<Pair<Integer, Integer>> generateElementaryIntervals(List<Pair<Integer, Integer> intervals)
我想象的解决方案之一是将输入分成不相交的集合,然后对每个不相交的集合中的所有数字进行简单的 O(NlogN) 排序将产生答案。有更有效的方法吗?
I came across a good question while preparing for some programming interviews.
Given a set of possibly overlapping intervals, you need to write a function to return all elementary intervals among them. For example: if you are given intervals as the following list of pairs: {{1,5}, {3,10}, {5,11}, {15,18}, {16,20}}, then you need to return the following:
{{1,3}, {3,5}, {5,10}, {10,11}, {15,16}, {16,18}, {18,20}}
Note the following in the above answer:
- The interval {11,15} is omitted in the answer because it is
non-existent in the input. - The interval {1,5} from the input has been split up into {1,3}, {3,5}
in the answer because of the starting point "3" defined in {3,10} in
the input that cuts the interval into two elementary intervals.
Method signature in Java:
List<Pair<Integer, Integer>> generateElementaryIntervals(List<Pair<Integer, Integer> intervals)
One of the solutions that I imagined was to separate the input into non-intersecting sets, and then a simple O(NlogN) sort over all numbers in each non-intersecting set will yield the answer. Is there a more efficient way to do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以先将此问题分解为嵌套区间,然后分别处理每个嵌套。我所说的嵌套是指至少共享一个点的间隔。对于您给出的示例:
有两个嵌套:
并且
一般来说,要确定嵌套,您可以根据左端点对间隔进行排序(如您的示例中所示),然后每当看到
{x,y}, {x',y'}
且y < x'
。对于嵌套,“基本间隔”由值的排序序列(不重复)形成。在示例中,嵌套给出
和
因此,整体算法可能如下所示:
{x,y}, {x',y'}
<代码> y < x'{x,y}
,制作端点排序列表(无重复),例如a0,a1,...,ak
{ai,a(i+1)}
fori = 0...k-1
{x,y}
的间隔代码> 并从步骤 2 继续You could break this problem up into nested intervals first, then deal with each nesting separately. By nested, I mean intervals that share at least one point. For the example you gave:
there are two nestings:
and
In general, to determine the nestings, you can sort the intervals based on the left endpoint (as in your example), then run through and start a new nesting whenever you see
{x,y}, {x',y'}
withy < x'
.For a nesting, the "elementary intervals" are formed by the sorted sequence (without repeats) of values. In the example, the nestings give
and
So the overall algorithm may look like this:
{x,y}, {x',y'}
withy < x'
{x,y}
, make sorted list of endpoints (no repeats), saya0,a1,...,ak
{ai,a(i+1)}
fori = 0...k-1
{x,y}
and continue from step 2您可以对端点进行排序,然后按顺序迭代。为了知道您是进还是出,您可以保留覆盖每个点的间隔数。
区间的左端贡献+1,而右端贡献-1:
(请注意,我使用 TreeMap,这是已排序)
You can sort the endpoints and then iterate in order. In order to know whether you are in or out you can keep the number of intervals that cover each point.
The left end of the interval contributes +1, while the right contributes -1:
(Note that I use TreeMap, which is sorted)
一个简单的算法是简单地读取整个数字列表,并为每对中的每个项目创建一个元素。
每个元素将存储两个值:
数字
,以及它是第一个数字还是第二个数字(来自输入)。然后,这些对将被排序,首先按其内部
数字
,然后按其位置(第二
将排在第一
之前)以打印出间隔列表,您可以将每个数字与下一个数字一起打印,并遵循以下规则:
第二个
数字,然后是第一个
数字,您不会打印该基本区间,因为该范围内没有值。A simple algorithm would be to simply read through the entire list of numbers, and create an element for each item in each pair.
Each element would store two values: the
number
, and whether it is the first or second number (from the input).Those pairs would then be sorted, first by its internal
number
, and then by its position (second
would go beforefirst
)To print out the list of intervals, you would print each number together with the next number, with the following rules:
second
number, and then afirst
number, you wouldn't print that elementary interval, since there are no values within that range.