..这里我的问题是我应该检查速度范围是否重叠,如果它们重叠,我应该显示一条消息,说明速度范围不能重叠。
Minimum Maximum Rate
1 15 10
16 25 15
答案 0 :(得分:1)
将每个速度范围视为连续数字线上的线段。为了找到所有重叠,在每个线段重叠处对数字线进行分区。
首先,将每个范围分成开始和结束点。假设你的范围是:
(5,8) (1,5) (14,17) (3,4) (5,10)
A=(5,8) B=(1,5) C=(14,17) D=(3,4) E=(5,10)
好的,现在,让我们将这些范围拆分为离散的起点和终点:
A[start]=5, A[end]=8, B[start]=1, B[end]=5, C[start]=14, C[end]=...
等。
按值对这些点进行排序,如果值相等,则起点位于结束点之前,以便得到如下列表:
B[start]=1, D[start]=3, D[end]=4, A[start]=5, E[start]=5, B[end]=5, A[end]=8, ...
等。
简单,对吧?
现在,只需遍历已排序的列表,保留当前范围的列表。每次进入[start]
点时,请将该范围添加到列表中。每次到[end]
点时,请从列表中取出范围。
所以对于上面的列表,你会去:
B[start]=1 add B => (B)
D[start]=3 add D => (B,D)
D[end]=3 remove D => (B)
A[start]=4 add A => (B,A)
E[start]=5 add E => (B,A,E)
B[end]=5 remove B => (A,E)
A[end]=8 remove A => (E)
... and so on
只要您的列表包含多个元素,那就是重叠。因此,对于任何范围,您都可以确切地确定哪个范围在任何特定点重叠。
假设您使用类似快速排序的算法对正在/结束点进行排序,那将是O(n log n)
运行时间,并且检测实际重叠是及时的线性,因此整个算法将在{{1}中运行}。
答案 1 :(得分:0)
如果您对值进行排序:
然后你可以按顺序迭代它们,然后检查下一个范围。重叠范围将在序列中彼此相邻。
在你的例子中:
但是,请注意,此算法仅回答“任何范围重叠”的问题,但它并未提供所有重叠组合。例如,在上面的代码中,1-16和15-25重叠,但是你没有得到这种实现的组合。
如果您需要,则需要更智能的算法。
我在这里发布了一个Visual Studio 2008项目:Subversion Repository for SO2696398。
主应用程序代码如下所示:
using System;
using System.Linq;
using LVK.Collections;
namespace SO2696398
{
public class Program
{
public static void Main(string[] args)
{
var ranges = new[]
{
new Range<int, double>(1, 15, 10),
new Range<int, double>(16, 25, 15),
new Range<int, double>(8, 22, 7),
};
var slices = ranges.Ordered<int, double>().Slice();
foreach (var slice in slices)
{
if (slice.Data.Length == 1)
continue;
Console.Out.WriteLine("overlap at " + slice.Start
+ "-" + slice.End + ": "
+ string.Join(" with ",
(from range in slice.Data
select range.ToString()
+ " [rate=" + range.Data + "]").ToArray()));
}
}
}
}
输出结果为:
overlap at 8-15: 1..15 [rate=10] with 8..22 [rate=7]
overlap at 16-22: 8..22 [rate=7] with 16..25 [rate=15]
希望这会有所帮助。项目的类部分是我在主类库中的一小部分类。如果您更愿意链接到完整库,则可以从Subversion Repository for LVK for .NET下载并编译源代码。这里使用的类来自LVK.Core项目。
答案 2 :(得分:0)
您可以在数据库中轻松实现此业务逻辑,以要求将来的任何应用程序都遵循此约束。
我会将逻辑实现为存储过程(或触发器),如下所示:
CREATE PROCEDURE MyDatabase.spInsertSpeedRanges
@Min int,
@Max int,
@Rate int
AS
select top 1 *
from tblSpeedRanges
where (Minimum between @Min and @Max) or (Maximum between @Min and @Max)
if @@RowCount <> 0
return -1
else
insert into tblSpeedRanges (Minimum, Maximum, Rate) values (@Min, @Max, @Rate)
GO
然后在您的应用程序中,如果返回-1,则显示您选择的错误消息。