幾種簡單的求素數算法的複雜度分析

    素數的算法有很多種,現在主要講兩種算法及其改進版本的複雜度分析,解釋性能提升的幅度。同時應用一個素數定理:素數的平方一定是合數,那麼在範圍內最大數的開方範圍內找不到能整除的數,那麼這個數是素數。應用這個定理可以將取模範圍的空間複雜度從O(n)降爲O(n**0.5).現以求100000內素數爲例,兩種算法分別是:
      1.基礎思路是去掉偶數,包括取模的範圍,代碼如下:

print(2)
for i in range(3,100000,2):
  for a in range(3,int(i**0.5)+1,2):
    if i%a == 0:
     break
    else:
     print(i,end = ' ')
'''

                            *此兩層循環的算法的計算複雜度爲(0.5*n*((n**0.5)+1)/2),空間複雜度爲O(n**1.5)

          2.應用一個素數定理:大於6的素數一定與6的倍數相鄰,代碼如下:
              '''
                print(2,3,end = ' ')
                 n = 100000
                 i = 5
           step = 2
                while i<= n:
                         for j in range(5,int(i**0.5)+1,2):
                                if j%j == 0:
                                    break
                            else:
                                    count += 1
                            i += step
                            step = 4 if step ==2 else 2
                                    '''
  1. 此算法的計算複雜度爲(n/3052)(n0.5+1)/2(將總範圍分成30爲一塊,則6的倍數有5個,相鄰的數就是10個),空間複雜度同樣爲O(n1.5)

                     優化思路:
                     對於1號算法,我們知道末尾是5的數一定能被5整除,所以末位是5的數一定不是素數,j計算複雜度可以降爲0.4*n*((n**0.5+1)*0.4)。不是偶數且末爲不是5,就剩(1,3,7,9),所以4/10=0.4,第二層循環也是如此。優化效率提升56%(0.5**2/0.4**2-1=0.56)。
                     對於2號算法,思路也是刨去末位爲5的數。例如,30~60這一塊內,6的倍數有(36,42,48,54,60),相鄰的數是(35,37,41,43,47,49,53,55,59,61),有兩個末位是5的數(35,55),所以將總範圍分成30爲一塊,只需計算8個數,優化後空間複雜度爲(n/30*(5*2-2))*(n**0.5+1)*0.4=4/15*n*(n**0.5+1)*0.4。相比優化後的1號算法,優化後的2號算法效率提升50%(其餘項約分,只剩0.4/(4/15),所以0.4/(4/15)-1=0.5)。
    
                    綜上可見,降低算法複雜度是提高解決問題效率的不二法門。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章