計算量オーダーについて O(1/n)オーダー?
こんにちは、c#初心者です。
今回は計算量オーダーの話なので、基本的に言語は関係ないと思います。
計算量オーダーの基本的な部分は分かるのですが、O(1/n)オーダーのアルゴリズムは(今のところは)まだ見かけないというか、名前程度しか知らないので、これに関しては無知です。そこで、この場合はどういうオーダーになっているのかという質問です。
質問は3つあります。
1)この一連の処理はO(1/n)オーダーになっているか?
int count = 1000 / length; // lengthは正の整数
for ( int i = 0; i < count; i++ ) Do(); // O(1)オーダーの処理
2) (1がO(1/n)の場合)繰り返す処理がO(n^2)になった場合に、この一連の処理はO(n)オーダーになるのか?
int count = 1000 / length; // lengthは正の整数
for ( int i = 0; i < count; i++ ) Do(); // O(n^2)オーダーの処理
3)配列型のコレクション(コレクションって、c#の呼び方だったっけ?) [c#] List<T>,[c++] Bector, [Java] ArrayList(だったっけ?)のようなクラスのAddメソッドのオーダーは?
//Addメソッドの中身
if ( Capacity == Count ) Expand(); // Expandは配列の容量を2倍に拡張するO(n)処理とします。
array[Count++] = item;
以上です。
補足で、2)については大学の教授に「一回でもO(n^2)の処理が呼び出されたら、O(n^2)オーダーになる」と言われましたが、納得いかないです。確かに、O(1/n)オーダーの処理の後にO(n^2)オーダーの処理を行えば、そうなるのは納得いくのですが……という感じです。教授が読み間違えたとは考えにくいですが(確かにちょっと忙しそうでしたが)、念のため質問です。
それと、3)はよくある配列型のコレクションのまねです。「もし内容物が容量一杯になれば拡張→追加」を繰り返すとした場合です。ExpandメソッドのオーダーがO(n)なので、単純に計算すればO(n)オーダーになるのですが、呼び出される頻度が「(拡張された容量)回に1回」です。
例えば、容量が4ずつ拡張されるとすれば、「4回に1回」拡張が必要になり、10ずつ拡張されるとすれば、「10回に1回」の拡張が必要です。この場合、どう考えても全体として定数で割っているだけなので、O(n)オーダーのままになるのは明白なのですが、今回は容量2倍とさせていただきました。すると拡張の頻度は「(さっきまでの容量)回に1回」の頻度で、容量に反比例し、直感的にはO(Count / Capacity) = O(1)オーダーに見えるのですが、この判断は正しいでしょうか?
皆さんのご意見を伺わせてください。
お礼
ありがとうございます。が、サイトを見てもいまいち(てかさっぱり)分かりません・・・(・・;)すいません、素人の私でも分かるようなざっくりとした解説を誰が詳しい方お願いします。