次の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はディクショナリ内のキーの数です。これは正しいです?
このルーチンは、全体として、事実上O(m)時間の複雑さであり、mは検索内の文字列の数です。
Dictionary.Contains と Dictionary.Add は両方とも(通常)O(1)演算であるためです。
(Dictionary.AddはO(n)のように、Dictionaryのn個のアイテムで使用できるため、それよりも少し複雑ですが、辞書の容量が小さい場合のみです。したがって、十分な容量のある辞書は、O(m))になります。)
そうは言っても、存在チェックにディクショナリのみを使用している場合は、HashSet<string>
。これはあなたが書くことを可能にするでしょう:
public void DistinctWords(String s)
{
HashSet<string> hash = new HashSet<string>(s.Split(' '));
// Use hash here...
ディクショナリはローカル変数であり、(少なくともコードには)保存されていないため、LINQを使用することもできます。
var distinctWords = s.Split(' ').Distinct();
Dictionary ...のドキュメントに記載されています.
Dictionaryジェネリッククラスは、キーのセットから値のセットへのマッピングを提供します。辞書への各追加は、値とそれに関連付けられたキーで構成されます。キーを使用して値を取得するのは非常に高速で、O(1)に近くなります。これは、Dictionaryクラスがハッシュテーブルとして実装されているためです。
そして Add 関数の場合:
カウントが容量より少ない場合、このメソッドはO(1)演算に近づきます。新しい要素に対応するために容量を増やす必要がある場合、このメソッドはO(n)操作。nはCountです。
どちらの方法にも一定の複雑さがあります。
それは正しくありません。通常、辞書/ハッシュテーブルの検索はO(1)です。これを行うには、探しているキーからハッシュを生成し、それを同じハッシュを持つアイテムとのみ比較します-優れたハッシュアルゴリズムを使用すると、これはO(1)全体と見なされます( 償却済み O(1)-O(n)がある追加のために容量を増やす必要があるまれな場合のみ)。
どちらも一定の時間です:
http://msdn.Microsoft.com/en-us/library/kw5aaea4.aspx
http://msdn.Microsoft.com/en-us/library/k7z0zy8k.aspx
ただし、1つの注意点があります。
「カウントが容量より少ない場合、このメソッドはO(1)演算に近づきます。新しい要素に対応するために容量を増やす必要がある場合、このメソッドはO(n)操作、nはカウントです。 "
ContainsKeyおよびAddメソッドはO(1)に近いです。
ContainsKeyのドキュメント:
このメソッドは、O(1)演算に近づきます。
ドキュメントを追加:
カウントが容量より少ない場合、このメソッドはO(1)演算に近づきます。新しい要素に対応するために容量を増やす必要がある場合、このメソッドはO(n)操作。nはCountです。
Framework 3.5以降を使用している場合は、HashSet<T>
ダミー値を持つ辞書の代わりに:
public void DistinctWords(String s) {
HashSet<string> d = new HashSet<string(s.split(" "));
}