この関数の時間の複雑さはどれくらいですか?


7

これは私の講義ノートの例です。この関数は時間の複雑さを伴いますかO(nlogn)?。最悪のケースは機能がelse分岐に入るので、時間の複雑性が2つの入れ子になったループlogn そして n、そうです O(nlogn)。私は正しいですか?

int j = 3;
int k = j * n / 345;
if(k > 100){
    System.out.println("k: " + k);
}else{
    for(int i=1; i<n; i*=2){
        for(int j=0; j<i; j++){
            k++;
        }
    }
}

回答:


5

上記のアルゴリズムの時間の複雑さは O(1)、なぜなら K>100 あなたは一定の操作(println)をしていて、あなたは知っています: j=3,k=3n/345100=3n/345n=11500、の意味 n11500 アルゴリズムの実行時間は一定です(他の部分も一定です。 n<11500 呼び出されます)。

より明確にするために、この質問を見てください。


多分ちょうどあなたの答えを完了するために、あなたは時間の複雑さについて話すとき、私たちは何が起こるかだけを気にすることを言及すべきです n。それとも、同じように、複雑さに対処する質問の一つにリンクすることができ、この1
蘭G.

@RanG。あなたは絶対的に正しい、実際私はBig-Ohの正式な定義を書くことを考えたが、実際にはあなたが見つけるのに十分であるため、誰もがこれを知っていると思ったn0 初期値の場合、 c0定数係数の場合。決めたn0、しかし私は言及しなかった c0(それは明らかであると思われます)しかし、はい、私はそれをラファエルの答えにリンクします(すべて私は書面で怠惰です)。

4

編集:Saeed Amiriが指摘したように、これは実際には O(1)、漸近的に大きいので nelse分岐は実際には行われません。if一部は自明時定数であり、実行されます。参考までに残しておきますが、この回答の残りの部分は、たとえば、条件がである場合は正しいでしょうk < 100。取り違えて申し訳ありません。

時間の複雑さは基本的にその回数のオーダーになります kネストされたforループで増分されます。いくつかの余分なことが起こっていますが、それについて考えれば、それは一定の要因で遊んでいるだけです。何回k 増加しますか?

いつ i=1kは1だけ増加します。いつi=2kさらに2回インクリメントされます。いつi=xk 増加します x追加の時間。それでは、n=2m+1。次に、内部ループの最後の反復により、kインクリメントされます2m 回。

k 総計が増加します 1+2+...+2m 回、または 2(m+1)1回。そのことを思い出してくださいn=2m+1。そうn1=2m、私たちはそれを持っています k 増加します 2(n1)1 合計時間。

k 線形である回数だけインクリメントされます n; エルゴ、これがすべてですO(n)


-1時間の複雑さはforループから独立しています。(私の答えを見て、自分で試してください)。

1
@SaeedAmiriおっと、あなたは正しい。私elseは、前提条件の内容を確認せずに、一部に磨きをかけました。これを反映するように回答を編集しています。
Patrick87

ええ、今あなたの答えは正しいです。

1

if / elseブランチに関するコメントはすべて正しいですが、答えはO(log n)と言えます。その理由は

System.out.println("k: " + k);

整数から文字列出力への変換を含み、これは一般的なケースではO(log n)になります(ルックアップテーブルが使用されている場合でも、各桁を出力するだけです)。

それが問題のトリックの一部だったかどうかわかりません...


0

どれどれ:

int j = 3; 一定時間O(1)かかります。

int k = j * n / 345j変数とn変数の対数時間関数を取ります

if (k > 100) 一定時間O(1)かかります。

System.out.println("k: " + k);kの対数時間関数をとります

for (int i=1; i<n; i*=2)tがこのforループの反復回数である場合、iの値は次のように表せるため、nの対数時間関数Θ(log(n))を正確に取る:i = 2 t-1、ただしt = 1最初の反復において、ループは限り続けて2 T-1 <Nであり、ここでnは変更されません。

微積分では、2 t-1 <nの場合t-1 <log 2(n)

そして、t-1 <log 2(n)の場合、t <log 2(n)+1

そして、各反復でtが1ずつ増加する場合、このforループ内のコードの実行時間の複雑さが一定、つまりO(1)の場合、このforループは実際にΘ(log(n))時間かかることがわかります。もちろん!

このforループ内には、別のforループがあります。

for (int j=0; j<i; j++) k++;

これを分析しましょう:

k++; 一定の時間、つまりO(1)時間かかります。

したがって、内部のforループの実行時間の複雑さを分析することは興味深いことです。

どれどれ:

この内部forループのコードによると、この内部forループにはi回の反復があるように見えます。そのため、実行時間はO(i)ではなくΘ(i)です。これは、途中で壊れないためです。しかしことを覚えておいてI <N なぜならループの外側のを、ときに初めに、それは1回の反復を取るようにもかかわらず、I 1 =ときに、2回の反復をI 2 =ときに、4回の反復をiが4 =ときに、8回の反復をiが8 =。 ..などなど、行i * = 2の外側のforループの終わりで自分自身が2倍になるため、合計で1 + 2 + 4 + 8 + ...の繰り返しになりますi≥nまでしたがって、この内部forループで可能な最大反復回数は、最悪の場合のi = n-1のときです。したがって、内部forループの最後の実行で、n-1回の反復が実行されたので、その前に( n-1)/ 2回の反復とその前に(n-1)/ 4回の反復が実行され、その前に(n-1)/ 8回の反復が実行されたので、合計で次のように実行されました。

n-1 +(n-1)/ 2 +(n-1)/ 4 +(n-1)/ 8 ... =(n-1)(1 + 1/2 + 1/4 + 1/8 ...)=(n-1)(2)= 2n-2 =Θ(n)

1 + 1/2 + 1/4 + 1/8 ... = 2は、よく知られた幾何学的シーケンスの合計であることを思い出してください。

外側のforループはΘ(log(n))をとることを思い出してください

そして、内側のforループはΘ(n)をとります。

また、forループの内側のforループの実行時間の複雑さは、外側のforループの実行時間の複雑さに内側のforループの実行時間の複雑さを掛けたものであるため、thus(nlogn)の実行時間がかかります。

したがって、要約すると、この関数の実行時間はΘ(nlogn)です。

これがあなたの質問にうまく答え、アルゴリズムと関数の実行時の複雑さを分析する方法をよく教えてくれることを願っています。


なぜ私の回答はすぐに反対票が投じられたのですか?
送別スタック交換

私の分析は間違っていますか?
送別スタック交換

「int k = j * n / 345は、jおよびn変数の対数時間関数を使用します」。数値では操作あたりの対数時間コストを使用していますが、質問でも意図されているように、通常は操作あたり一定の時間コストが使用されます。さらに、jは内側のループのiまでしか実行されないため、2つのループの分析は間違っています。他の誰かが述べたように、O(n)は正しいです。
アルバートヘンドリックス2017

はい、同意します。
Farewell Stack Exchange
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.