HashSet(T).Contains(T)
(继承自ICollection<T>.Contains(T)
)的时间复杂度为O(1)
所以,我想知道包含整数的类成员数组的复杂性是什么,因为我努力实现O(1)并且不需要HashSet(T).Add(T)
{{1}}。< / p>
由于.NET引用源中显示existence checks 而不是,因此我无法找到找到built-in types的数组实现。
非常感谢任何(进一步)阅读材料或参考资料。
答案 0 :(得分:7)
您可以看到Array
的源代码与任何反射器(也可能在线,没有检查)。 IList.Contains
只是:
Array.IndexOf(this,value) >= this.GetLowerBound(0);
Array.IndexOf
调用Array.IndexOf<T>
,经过一系列一致性检查后,重定向到
EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count)
那个人终于做到了:
int num = startIndex + count;
for (int index = startIndex; index < num; ++index)
{
if (this.Equals(array[index], value))
return index;
}
return -1;
因此,只需循环遍历平均复杂度为O(N)
的数组。当然,从一开始就很明显,但只是为了提供更多的证据。
答案 1 :(得分:4)
数组源代码在reference source中可用,可以使用ILSpy进行反编译。
在参考源中,您可以在第2753行找到2809:
// ----------------------------------------------------------- // ------- Implement ICollection<T> interface methods -------- // ----------------------------------------------------------- ... [SecuritySafeCritical] bool Contains<T>(T value) { //! Warning: "this" is an array, not an SZArrayHelper. See comments above //! or you may introduce a security hole! T[] _this = JitHelpers.UnsafeCast<T[]>(this); return Array.IndexOf(_this, value) != -1; }
而IndexOf
最终会以IndexOf
结束,这是一种O(n)算法。
internal virtual int IndexOf(T[] array, T value, int startIndex, int count) { int endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { if (Equals(array[i], value)) return i; } return -1; }
这些方法位于同一源文件中的特殊类SZArrayHelper上,如第2721行所述,这是您正在寻找的实现。
// This class is needed to allow an SZ array of type T[] to expose IList<T>, // IList<T.BaseType>, etc., etc. all the way up to IList<Object>. When the following call is // made: // // ((IList<T>) (new U[n])).SomeIListMethod() // // the interface stub dispatcher treats this as a special case, loads up SZArrayHelper, // finds the corresponding generic method (matched simply by method name), instantiates // it for type <T> and executes it.
关于实现O(1)复杂性,您应该将其转换为HashSet:
var lookupHashSet = new HashSet<T>(yourArray);
...
var hasValue = lookupHashSet.Contains(testValue);
当然,这种转换是O(n)操作。如果你没有很多查询要做,那就没有用了。
请注意此构造函数上的from documentation:
如果集合包含重复项,则集合将包含每个唯一元素之一。不会抛出异常。因此,结果集的大小与集合的大小不同。
答案 2 :(得分:0)
您实际上可以看到List<T>
的来源,但您需要在线查找。这是one source。
任何纯列表/数组bool Contains(T item)
检查都是O(N)复杂度,因为需要检查每个元素。 .NET也不例外。 (如果您设计的数据结构表现为列表,但也包含布隆过滤器辅助数据结构,那将是另一个故事。)