【问题标题】:What is the complexity of these Dictionary methods?这些 Dictionary 方法的复杂性是什么?
【发布时间】:2011-11-23 20:44:26
【问题描述】:

谁能解释以下Dictionary 方法的复杂性?

ContainsKey(key)
Add(key,value);

我正在尝试弄清楚我编写的方法的复杂性:

public void DistinctWords(String s)
{
    Dictionary<string,string> d = new Dictionary<string,string>();
    String[] splitted = s.split(" ");
    foreach ( String ss in splitted)
    { 
        if (!d.containskey(ss))
            d.add(ss,null);
    } 
}

我假设这 2 个字典方法具有 log(n) 复杂性,其中 n 是字典中的键数。这是正确的吗?

【问题讨论】:

  • 不,我相信ContainsKeyAdd 在一般情况下都是常数时间。 编辑:您还应该查看HashSet。它可以更干净地完成您尝试使用Dictionary 的操作。

标签: c# complexity-theory time-complexity


【解决方案1】:

这个例程作为一个整体,实际上是 O(m) 时间复杂度,其中 m 是搜索中的字符串数。

这是因为Dictionary.ContainsDictionary.Add 都是(通常)O(1) 运算。

(比这稍微复杂一点,因为 Dictionary.Add 对于字典中的 n 个项目可以是 O(n),但仅当字典容量较小时。因此,如果您构建的字典具有足够大的容量在前面,m 个字符串条目将是 O(m)。)

话虽如此,如果您只使用字典进行存在性检查,您可以使用HashSet&lt;string&gt;。这将允许您编写:

  public void DistinctWords(String s)
  {
     HashSet<string> hash = new HashSet<string>(s.Split(' '));

     // Use hash here...

由于您的字典是一个局部变量,并且没有存储(至少在您的代码中),您也可以使用 LINQ:

 var distinctWords = s.Split(' ').Distinct();

【讨论】:

  • 小容量字典的检索时间为 O(n) 怎么办?文档提到哈希表在幕后。因此复杂度应该是 O(1)
  • @ShahryarSaljoughi 之所以是 O(M) 是因为 M 是上面示例中的字符串数量...即使您执行 O(1) 操作,您也执行 M 次
【解决方案2】:

ContainsKey 和 Add 方法接近 O(1)。

包含关键文档:

此方法接近 O(1) 操作。

添加文档:

如果 Count 小于容量,则此方法接近 O(1) 手术。如果必须增加容量以适应新的 元素,这个方法变成了一个 O(n) 操作,其中 n 是 Count。

如果您使用的是 Framework 3.5 或更高版本,您可以使用 HashSet&lt;T&gt; 代替具有虚拟值的字典:

public void DistinctWords(String s) {
  HashSet<string> d = new HashSet<string(s.split(" "));
}

【讨论】:

    【解决方案3】:

    两者都是常数时间:

    http://msdn.microsoft.com/en-us/library/kw5aaea4.aspx

    http://msdn.microsoft.com/en-us/library/k7z0zy8k.aspx

    但有一个警告:

    “如果 Count 小于容量,则此方法接近 O(1) 操作。如果必须增加容量以容纳新元素,则此方法变为 O(n) 操作,其中 n 是 Count。”

    【讨论】:

      【解决方案4】:

      它写在Dictionary的文档中...

      Dictionary 泛型类提供从一组键到一组值的映射。字典中的每个添加都包含一个值及其关联的键。使用其键检索值非常快,接近 O(1),因为 Dictionary 类是作为哈希表实现的。

      对于Add 函数:

      如果 Count 小于容量,则此方法接近 O(1) 操作。如果必须增加容量以容纳新元素,则此方法变为 O(n) 操作,其中 n 为 Count。

      【讨论】:

        【解决方案5】:

        这两种方法都具有恒定的复杂性:

        • ContainsKey(key) - O(1)
        • 添加(键,值) - O(1)

        【讨论】:

        • ContainsValue 方法呢?
        • ContainsValue 为 O(n)。
        【解决方案6】:

        这是不正确的,通常字典/哈希表查找是 O(1)。为此,它将从您正在寻找的密钥中生成一个哈希,并且仅将其与具有相同哈希的项目进行比较 - 使用良好的哈希算法,这被认为是 O(1) 整体(amortized O(1) - 仅在极少数情况下必须增加容量才能添加 O(n))。

        【讨论】:

        • “将其与具有相同哈希的项目进行比较”。为了看到相同的哈希项,它不需要迭代吗?
        • 使用好的散列算法,碰撞是非常罕见的,你只需要遍历碰撞列表
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-27
        • 2021-10-28
        • 1970-01-01
        • 2011-09-03
        • 1970-01-01
        相关资源
        最近更新 更多