寻找类似于HashSet的东西,但具有键值的范围
本文关键字:键值 范围 类似于 HashSet 寻找 | 更新日期: 2023-09-27 18:03:27
我想知道是否有类似HashSet的东西,但由一系列值键。
例如,我们可以添加一个键值为100到4000之间所有整数的项。如果我们使用100到4000之间的任何键,例如287,则该项将被返回。
我希望查找速度非常接近HashSet,即O(1)。可以使用二进制搜索来实现这一点,但是对于需求来说,这太慢了。我希望尽可能使用标准的。net API调用。
这很有趣:https://github.com/mbuchetics/RangeTree
它的时间复杂度为O(log(N)),其中N是间隔的数量,所以它不完全是O(1),但它可以用来构建一个工作实现。
我不相信已经有一个结构了。你可以实现像RangedDictionary:
这样的东西class RangedDictionary {
private Dictionary<Range, int> _set = new Dictionary<Range, int>();
public void Add(Range r, int key) {
_set.Add(r, key);
}
public int Get(int key) {
//find a range that includes that key and return _set[range]
}
}
struct Range {
public int Begin;
public int End;
//override GetHashCode() and Equals() methods so that you can index a Dictionary by Range
}
编辑:将HashSet改为Dictionary
您可以尝试一下这个解决方案。然而,它假设了一些点:
- 无范围重叠
- 当你请求一个号码时,它有效地在一个范围内(没有错误检查)
从你说的来看,这个是O(N),但我认为你可以毫不费力地把它变成O(log(N))。
这个想法是一个类将处理范围的事情,它将基本上转换任何值给它的范围的下限。这样你的哈希表(这里是一个字典)包含低边界作为键。public class Range
{
//We store all the ranges we have
private static List<int> ranges = new List<int>();
public int value { get; set; }
public static void CreateRange(int RangeStart, int RangeStop)
{
ranges.Add(RangeStart);
ranges.Sort();
}
public Range(int value)
{
int previous = ranges[0];
//Here we will find the range and give it the low boundary
//This is a very simple foreach loop but you can make it better
foreach (int item in ranges)
{
if (item > value)
{
break;
}
previous = item;
}
this.value = previous;
}
public override int GetHashCode()
{
return value;
}
}
下面测试一下。
class Program
{
static void Main(string[] args)
{
Dictionary<int, int> myRangedDic = new Dictionary<int,int>();
Range.CreateRange(10, 20);
Range.CreateRange(50, 100);
myRangedDic.Add(new Range(15).value, 1000);
myRangedDic.Add(new Range(75).value, 5000);
Console.WriteLine("searching for 16 : {0}", myRangedDic[new Range(16).value].ToString());
Console.WriteLine("searching for 64 : {0}", myRangedDic[new Range(64).value].ToString());
Console.ReadLine();
}
}
我不相信你真的可以低于O(Log(N)),因为你没有办法立即知道一个数字在哪个范围内,你必须总是将它与下界(或上界)进行比较。
如果您有预先确定的范围,那将更容易做到。例如,如果你的范围是每百位,通过计算它对100取模就可以很容易地找到任何数字的正确范围,但这里我们不能做任何假设,所以我们必须检查。
要使用此解决方案向下到Log(N),只需将foreach替换为一个循环,该循环将查看数组的中间,然后每次迭代将其分成两部分…