我有一些排序数据,它们具有每个范围的起始和结束整数,并且它们是连续的。所以我的数据可能如下所示:
Number Start End
0 0 47
1 48 94
2 95 287
3 288 1123
等等。
我会得到一个像113
这样的整数,我希望以最快的方式搜索数据以找到匹配的数字。我可以将数据粘贴到一些优化检索/比较速度的结构中。
我的数据非常大。
编辑: 我选择了一个答案,这是我最终得到的代码:
Public Function EndingCaptureNumber(CaptureEnd As Integer) As Integer
EndingCaptureNumber = CaptureEnds.BinarySearch(CaptureEnd)
If EndingCaptureNumber < 0 Then
Return (Not EndingCaptureNumber) - 1
End If
End Function
捕获结束是每个范围结束的列表。不是恭维。由于这会发现第一个更大,我减去1得到最后一个不大。
编辑:重复问题重新审核
由此产生的答案使用内置的BinarySearch,但处理不完全匹配的值。寻求其他文章的搜索者不会学习这个(imho)更好的答案。另外,另一个问题是OP在他的RL问题中使用的实际数据类型混乱。
答案 0 :(得分:2)
由于您只需要下限,您可以将其存储在SortedList<int, int>
中,其中键是下限,值是数字,如下所示:
static SortedList<int, int> Ranges = new SortedList<int, int>
{
{0, 0}, {48, 1}, {95, 2}, {288, 3}
};
现在您可以使用此扩展方法查找下一个更高数字的索引:
private static int BinarySearch<T>(IList<T> list, T value)
{
if (list == null)
throw new ArgumentNullException("list");
var comp = Comparer<T>.Default;
int lo = 0, hi = list.Count - 1;
while (lo < hi)
{
int m = (hi + lo) / 2; // this might overflow; be careful.
if (comp.Compare(list[m], value) < 0) lo = m + 1;
else hi = m - 1;
}
if (comp.Compare(list[lo], value) < 0) lo++;
return lo;
}
public static int FindFirstIndexGreaterThanOrEqualTo<T, U>(this SortedList<T, U> sortedList, T key)
{
return BinarySearch(sortedList.Keys, key);
}
(对此答案的肯定:https://stackoverflow.com/a/594528/284240)
...并按照以下代码获取数字:
int number;
int find = 113;
int pos = Ranges.FindFirstIndexGreaterThanOrEqualTo(find);
if (pos > 0)
{
int key = Ranges[pos];
if(key == find)
number = Ranges[Ranges.Keys[pos]]; // matches lowerbound
else
number = Ranges[Ranges.Keys[pos - 1]]; // in range
}
答案 1 :(得分:0)
我认为这是最快捷的方式。但是,它必须设置并使用大量内存。
int[] Numbers = new int[100000];
for (int i = 0; i <= 47; i++)
Numbers[i] = 0;
for (int i = 48; i <= 94; i++)
Numbers[i] = 1;
for (int i = 95; i <= 287; i++)
Numbers[i] = 2;
for (int i = 288; i <= 1123; i++)
Numbers[i] = 3;
int Result = Numbers[113]; // Fast!
答案 2 :(得分:0)
坚持二元搜索。如果您有N个范围并查找K个数字,则搜索将采用O(KlogN)。
使用@Steve Wellens建议传播一切将需要大量的设置 - O(R)(R是最后一个范围结束 - 在你的例子中是1123)。设置完成后,K搜索将采用O(K),因此您正在查看O(K + R)
现在,如果最大数量小于KlogN,并且内存不是问题,则展开范围。如果不是(这是我的猜测,你说你有很多数据),二进制搜索会更快。