寻找像HashSet这样的东西,但是有一系列的键值?

时间:2016-08-22 10:27:40

标签: c# .net

我想知道是否有像HashSet这样的东西,但是键入了一系列值。

例如,我们可以添加一个项目,该项目键入100到4000之间的所有整数。如果我们使用100到4000之间的任何键,例如,将返回此项目。 287。

我希望查找速度非常接近HashSet,即O(1)。可以使用二进制搜索来实现这一点,但这对于要求来说太慢了。我想尽可能使用标准的.NET API调用。

更新

这很有趣:https://github.com/mbuchetics/RangeTree

它的时间复杂度为O(log(N)),其中N是区间数,因此它不完全是O(1),但它可以用于构建工作实现。

2 个答案:

答案 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替换为将查看数组中间的循环,然后在每次迭代中将其拆分为两个...

相关问题