1. 程式人生 > >尋找倍數的時間復雜度分析

尋找倍數的時間復雜度分析

false 篩法 int 總數 prim rac 普通 因此 rime

  經常能遇到類似於這樣的情況,給出一個n,尋找[1,n]中每個數x的所有落於[1,n]中的倍數。

  舉一個比較常見的例子,我們用普通的篩法尋找[1,n]之間的所有素數並標記。代碼大概如下:

isPrime = new int[n + 1]
for(i = 1; i <= n; i++)
    isPrime[i] = true
isPrime[1] = false
for(i = 2; i <= n; i = i + 1)
    for(j = i + i; j <= n; j = i + i)
         isPrime[j] = false

  很容易發現對於數x,在區間[1,n]中其倍數數目為floor(n/x)。而累加每個數,倍數的總數為$ \sum_{i=1}^n{\lfloor\frac{n}{i}\rfloor} $。很容易發現這個值的既是我們上面程序的時間復雜度,那麽這個值大約是多少呢?

  很容易發現這個值的一個上界$ n\sum_{i=1}^n{\frac{1}{i}} $,之後我們把視角移動到新的上界上來。註意到下面不等式的成立(想起黎曼積分的定義):

$$ \int_i^{i+1}{\frac{1}{x}dx}\le\frac{1}{i}\le\int_{i-1}^i{\frac{1}{x}dx} $$

進行累加可以得到:

$$ \int_1^{n+1}{\frac{1}{x}dx}\le\sum_{i=1}^n{\frac{1}{i}}\le 1+\int_1^n{\frac{1}{x}dx}\Rightarrow\ln\left(n+1\right)\le\sum_{i=1}^n{\frac{1}{i}}\le 1+\ln n $$

因此上面程序的時間復雜度就可以表示為O(nln(n)),是一個相當不賴的時間復雜度。當然還有許多可以優化的空間,甚至還可以優化為線性的歐拉篩。

尋找倍數的時間復雜度分析