我会:
- 保持一个“开放”范围的无序列表。
- 从第一天开始,将第一个范围添加到“开放”范围列表中。
- 移动到下一个范围边界(无论是开始还是结束)。创建你的第一个“输出”范围:从第一天开始,到那一天结束。其中包含在你的开放范围列表中的项。
- 如果遇到的范围已经在开放范围列表中,则将其删除。否则,添加它。
- 重复步骤3和4,沿着线移动。
我肯定没有好好解释清楚。我很快就会为此编写一些代码。但在此之前,请看一下在您的解决方案中会发生什么:
a |------------------------------|
b |-------------------|
c |-----------------|
1. 从第一天开始,加入A到开放范围列表中,现在列表为[A]
2. 移动到C的起始位置。第一个结果区间:从第一天到C的起始位置的范围,
值为A(即开放范围列表中的内容)
3. 将C添加到开放范围列表中,现在列表为[A,C]
4. 移动到B的起始位置。第二个结果区间:从C的起始位置到B的起始位置的范围,
值为A,C(即开放范围列表中的内容)
5. 将B添加到开放范围列表中,现在列表为[A,C,B]
6. 移动到C的结束位置。第三个结果区间:从B的起始位置到C的结束位置的范围,
值为A,C,B
7. 从开放范围列表中删除C,现在列表为[A,B]
8. 移动到A的结束位置。第四个结果区间:从C的结束位置到A的结束位置的范围,
值为A,B
9. 从开放范围列表中删除A,现在列表为[B]
10. 移动到A的结束位置。第五个结果区间:从A的结束位置到B的结束位置的范围,
值为B
结果区间:
1. 从第一天到C的起始位置:A
2. 从C的起始位置到B的起始位置:A,C
3. 从B的起始位置到C的结束位置:A,C,B
4. 从C的结束位置到A的结束位置:A,B
5. 从A的结束位置到B的结束位置:B
另一种方法
您可以按照以下步骤进行:
- 维护一个“输出范围”的有序列表。 这使得测试点是否在范围内以及哪些范围相互跟随变得容易。
- 获取输入范围。
- 检查它完全在所有输出范围之前或之后,如果是这样则进行处理并跳过下一步返回第2步。
- 将其起始点与输出范围进行比较。
- 如果它在任何其他输出范围之前,则添加一个新的输出范围从其起始点到第一个输出范围的起始点。
- 如果它在已存在的输出范围之间,则在该点拆分输出范围。 第一部分将保持相同的“父项”,而第二部分将具有相同的“父项”+新的输入范围。
- 现在,将其结束点与输出范围进行比较。
- 如果它在任何其他输出范围之后,则添加一个新的输出范围,从最后一个输出范围的结束点到其结束点。
- 如果它在已存在的输出范围之间,则在该点拆分输出范围。 第二部分将保持相同的“父项”,而第一部分将具有相同的“父项”+新的输入范围。
- 将当前输入范围作为步骤6和9中两个“处理过”的范围之间所有范围的一部分添加。
- 对所有输入范围重复步骤2-6。
以下是使用示例数据+另一个范围D的前几个步骤:
(用 **双星号** 表示“处理过”的范围)
<code>a |------------------------------|
b |-------------------|
c |-----------------|
d |------------------------|
</code>
1.
进程A
输出范围: |--------------A---------------|
2.
进程B
- B的开始在**A**中; 将A分为两部分:
|-------A-------|------AB------|
- B的结束在任何输出范围之后;
在结尾处创建新的输出范围
|-------A-------|------AB------|---B---|
- **A**和(无)之间没有任何内容。
3.
进程C
- C的开始在**A**中; 将A分为两部分:
|---A----|--AC--|------AB------|---B---|
- C的结束在**AB**中; 将AB分为两部分:
|---A----|--AC--|--ABC--|--AB--|---B---|
- **A**和**AB**之间没有范围
4.
进程D
- D的开始在**A**中; 将A分为两部分:
|-A-|-AD-|--AC--|--ABC--|--AB--|---B---|
- D的结束在**AB**中; 将AB分为两部分:
|-A-|-AD-|--AC--|--ABC--|ABD|AB|---B---|
- 范围AC和ABC在**A**和**AB**之间
|-A-|-AD-|--ACD-|-ABCD--|ABD|AB|---B---|
最终输出: |-A-|-AD-|--ACD-|-ABCD--|ABD|AB|---B---|