web-dev-qa-db-ja.com

ネストされたループのBig-Oとは何ですか?内側のループの反復数は、外側のループの現在の反復によって決定されますか?

次のネストされたループのBig-O時間の複雑さは何ですか。

for(int i = 0; i < N; i++) 
{
    for(int j = i + 1; j < N; j++)
    {
        System.out.println("i = " + i + " j = " + j);
    }

}

O(N ^ 2)でしょうか?

43
mmcdole

ええ、それはまだO(n ^ 2)で、定数係数は小さくなっていますが、それはO表記には影響しません。

37
Alex Gaynor

はい。 Big-Oの定義を思い出してください:O(f(n))定義により、ランタイムT(n)kf(n)一定の定数kの場合。この場合、ステップ数は(n-1)+(n-2)+ ... +となり、0からn-1の合計に再配置されます。これは

T(n(n-1)((n-1)+1)/ 2)==。

それを並べ替えると、T(n)が常に≤1/2(n²)になることがわかります。定義により、したがってT(n O(n²))==です。

27
Charlie Martin

System.out.printlnを無視すると、Nの2乗になります。その出力にかかる時間が線形であることを想定している場合(もちろん、そうでない場合もあります)、最終的にO((N ^ 2)* log N)になると思います。

私はこれをうるさいというわけではなく、複雑さを計算するときに明白なループを考慮する必要がないことを指摘するだけです。あなたが呼ぶものの複雑さも調べる必要があります。

12
Jon Skeet

はい、Nの2乗になります。実際のステップ数は、1からNの合計、つまり.5 *(N-1)^ 2です。 Big Oは最高の指数のみを考慮し、定数は考慮しないため、これは依然としてNの2乗です。

3
Charles Graham

N = 10の場合、反復は10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1になります。 (これは、10回の反復+ 9回の反復+ 8回の反復などです)。

ここで、Nを何回得ることができるか(例では10)を加算に見つける必要があります。

1:(10)、2:(9 + 1)、3:(8 + 2)、4:(7 + 3)、5:(6 + 4)。これは5回です...そして5回の反復を行います。

これで、5の数+ 5があることがわかります。

10(5)+ 5

f(n)(またはN)の観点から、これは次のようになることが簡単にわかります。

f(n)= n(n/2) + n/2 =(n ^ 2)/ 2 + n/2 =(n ^ 2 + n)/ 2 ...これまさにこれらのネストされたループの複雑さです。

しかし、Big Oの漸近的な振る舞いを考えると、単一のnと分母であるf(n)のあまり重要でない値を取り除くことができます。

結果:O(n ^ 2)

3
Jorge Gil

指定されたプログラムの場合:

for (int i = 0; i < n; i++)
    for (int j = i; j < n; j++)
        println(...);

N = 3を考えます。

iの値は0、1、2です。

For i = 0: println will execute 3 times
for i = 1: println will execute 2 times
for i = 2: println will execute 1 times

したがって、println関数は3 + 2 + 1回、つまりn(n + 1)/ 2回実行されます。

したがって、O(n(n + 1)/ 2)= O(n ^ 2)です。

0
Ashwin

AFAILは、内側のループから外側のループまで開始されるので、ネストされたループの複雑さを計算するのに適切な方法です。 enter image description here

0
snr