web-dev-qa-db-ja.com

Sieve of Eratosthenesアルゴリズムの時間計算量

から Wikipedia:

アルゴリズムの複雑さはO(n(logn)(loglogn))ビット操作です。

どうやってそこに着きますか?

複雑さがloglognの用語を含むことは、どこかにsqrt(n)があることを示しています。


最初の100個の数字(n = 100)でふるいを実行していると仮定します。数字を複合としてマークするのに一定の時間がかかると仮定すると(配列の実装)、mark_composite()を使用する回数は

n/2 + n/3 + n/5 + n/7 + ... + n/97        =      O(n^2)                         

そして、次の素数を見つけるために(たとえば、7の倍数であるすべての数を消した後に5にジャンプするため)、操作の数はO(n)になります。

したがって、複雑さはO(n^3)になります。 同意しますか?

84
Lazer
  1. 項の数が一定ではないため、n/2 + n/3 + n/5 +…n/97はO(n)ではありません。 [編集後の編集:O(n2)緩い上限は。]緩い上限はn(1 + 1/2 + 1/3 + 1/4 + 1/5 + 1/6 +…1/n)(-の逆数の合計all最大n)までの数字、これはO(n log n)です- 調和数 を参照してください。より適切な上限はn(1/2 + 1/3 + 1/5 + 1/7 +…)、つまりnまでの素数の逆数の合計、つまりO(n log log n)です。 ( here または here を参照してください。)

  2. 「次の素数を見つける」ビットはO(n)全体、 amortized total 、ステップごとではないため、アルゴリズムのこの部分はO(n)のみを取ります。

したがって、これら2つを使用すると、O(n log log n)+ O(n) = O(n log log n)算術演算の上限が得られます。ビット演算をカウントする場合、 'nまでの数を処理しているので、それらは約log nビットを持ちます。これは、log nの係数が入る場所で、O(n log n log log n)ビット操作を与えます。

109
ShreevatsaR
  1. 内部ループは_n/i_ステップを実行します。ここで、iは素数=>全体の複雑さはsum(n/i) = n * sum(1/i)です。素調和列によると、iが素数であるsum (1/i)log (log n)です。合計で、O(n*log(log n))
  2. 上のループはnsqrt(n)に置き換えることで最適化できると思うので、全体的な時間の複雑さはO(sqrt(n)loglog(n))になります。

    _void isprime(int n)
    {
        int prime[n],i,j,count1=0;
        for(i=0;i<n;i++)
        {
           prime[i]=1;
        }
        prime[0]=prime[1]=0;
        for(i=2;i<=n;i++)
        {
            if(prime[i]==1)
            {
                printf("%d ",i);
                for(j=2;(i*j)<=n;j++)
                    prime[i*j]=0;
            }
        }    
    }
    _
8
anand tripathi

複雑度にloglognの用語が含まれていることは、どこかにsqrt(n)があることを示しています。

ふるい分け中に素数Pを見つけた場合、現在の位置+ Pで数字の交差を開始しないことに注意してください。実際にP^2で数字の交差を開始します。 P^2より小さいPのすべての倍数は、以前の素数で相殺されます。

8
jemfinch

上記の説明を参照してください。内側のループは、sqrt(n)までのすべての素数の調和和です。したがって、実際の複雑さはO(sqrt(n)* log(log(sqrt(n))))です