我想知道是否有像HashSet这样的东西,但是键入了一系列值。
例如,我们可以添加一个项目,该项目键入100到4000之间的所有整数。如果我们使用100到4000之间的任何键,例如,将返回此项目。 287。
我希望查找速度非常接近HashSet,即O(1)。可以使用二进制搜索来实现这一点,但这对于要求来说太慢了。我想尽可能使用标准的.NET API调用。
更新
这很有趣:https://github.com/mbuchetics/RangeTree
它的时间复杂度为O(log(N)),其中N是区间数,因此它不完全是O(1),但它可以用于构建工作实现。
答案 0 :(得分: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
答案 1 :(得分:1)
这是您可以尝试的解决方案。但它假设了一些观点:
根据你的说法,这个是O(N),但你可以毫不费力地把它作为O(log(N))。
这个想法是一个类将处理范围事物,它基本上将给予它的任何值转换到它的范围的下边界。这样,你的Hashtable(这里是一个Dictionary)包含低边界作为键。
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替换为将查看数组中间的循环,然后在每次迭代中将其拆分为两个...