考虑以下描述连续integer
值范围的接口。
public interface IRange {
int Minimum { get;}
int Maximum { get;}
IRange LargestOverlapRange(IEnumerable<IRange> ranges);
}
我正在寻找一种有效的算法来找到给定IRange
对象列表的最大重叠范围。下图简要概述了这个想法。上面的数字代表integer
值,|-----|
代表IRange
具有最小值和最大值的对象。我堆叠了IRange
对象,以便解决方案易于可视化。
0123456789 ... N
|-------| |------------| |-----|
|---------| |---|
|---| |------------|
|--------| |---------------|
|----------|
在这里,该LargestOverlapRange
方法将返回:
|---|
由于该范围共有 4 个“重叠”。如果有两个IRange
相同数量的重叠,我想返回null
.
这是我尝试过的一些简短代码。
public class Range : IRange
{
public IRange LargestOverlapRange(IEnumerable<IRange> ranges) {
int maxInt = 20000;
// Create a histogram of the counts
int[] histogram = new int[maxInt];
foreach(IRange range in ranges) {
for(int i=range.Minimum; i <= range.Maximum; i++) {
histogram[i]++;
}
}
// Find the mode of the histogram
int mode = 0;
int bin = 0;
for(int i =0; i < maxInt; i++) {
if(histogram[i] > mode) {
mode = histogram[i];
bin = i;
}
}
// Construct a new range of the mode values, if they are continuous
Range range;
for(int i = bin; i < maxInt; i++) {
if(histogram[i] == mode) {
if(range != null)
return null; // violates two ranges with the same mode
range = new Range();
range.Minimum = i;
while(i < maxInt && histrogram[i] == mode)
i++;
range.Maximum = i;
}
}
return range;
}
}
这涉及四个循环,如果不是更高的话,很容易 O(n^2)。是否有更有效的算法(速度方面)从其他范围列表中找到最大的重叠范围?
编辑
是的,O(n^2) 不正确,我想错了。正如评论中指出的那样,它应该是 O(N * M)。
编辑 2
让我规定一些事情,值的绝对最小值和最大值integer
将来自 (0, 20000)。其次,平均数量IRange
将在 100 左右。我不知道这是否会改变算法的设计方式。
编辑 3
我在科学仪器(质谱仪)上实施该算法,其中数据处理的速度对数据质量至关重要(更快的分析时间 = 在时间 T 内收集的更多光谱)。固件语言(专有)只有数组[],不是面向对象的。我选择 C# 是因为我擅长在两种语言之间移植概念,并认为为了 SO 社区的利益,一个好的答案会吸引更广泛的受众。