快速求1000,000範圍內的所有素數,複雜度為O(n)

來源:互聯網
上載者:User

今天收穫不小啊,自創了一個快速O(n)複雜度的求1 ---- 1000,000範圍內的所有素數

 

註:這個方法確實是自創,如果有人想轉,請註明本文來處,否則我會很不爽的

 

思路:首先定義一個isPrime[1000001]的數組,初始化為0;isPrime[i] = 0表示i還沒有確定是否是素數,isPrime[i] = 1表示i一定不是素數

 

 

            對於一個數,他一定是由某些素數相乘得到的,那麼假如我們得到了一個x為素數,那麼可以利用x去掉比x大的是x的倍數的數

 

           但是這樣的話還是不夠,因為x從2到1000,000的遍曆,x的倍數也要從x往1000,000遍曆,鐵定不行

 

          這個時候,我們可以發現連個可以最佳化的地方(下面講“判定”這個詞的時候,意思就是判定是否為素數)(顯然,當x遍曆到一個isPrime【x】==0的時候,說明x沒能被比x小的素數判定為合數,x肯定沒有比x大的因子,所以x肯定是素數)

          (1),x的倍數x*y,判定x*y的時候,y不必比x小,因為如果y比x小,那麼x*y一定在之前已經被判定了;如何解釋:分兩種情況,如果y是素數,那麼x*y已經被y判定過,如果y不是素數,那麼x*y一定被y的因子判定過,這時候x*y不用判定

 

          (2),x的倍數x*y,y一定不是已經被判定為isPrime【y】 = 1,即y一定不是素數,也就是說y是合數,那麼這時候y的因子肯定小於或者等於x(注意有等於的情況,後面解釋等於的情況要特殊處理),因為y已經被判定了,這個因子也一定是x*y的因子,那麼x*y也已經被判定為不是素數了

 

          談最佳化,我們可以把所有的2—1000,000用一個雙向鏈表存起來,用where[i]表示i的鏈表中的節點地址,當i被判定為不是素數時就可以把i從鏈表中刪除,利用where就可以不用遍曆,O(1)的時間刪除

         每次得到一個素數,遍曆鏈表,得到判定為合數的數,刪除這個數剪短鏈表直到這個數大於1000,000就跳出遍曆,那麼每遍曆一個節點就刪除一個節點,這個演算法的複雜度可以理解為1000,000長度的鏈表在O(n)次的操作中遍曆多少節點就刪除多少節點,總的複雜度當然就是O(n)了

 

      特別注意,我們不能從素數x判定到一個數z為合數就把他從鏈表中刪除,為什麼,因為z的所有因子都是x,那麼刪除了z,那麼z*x就沒法判定了,對於這種情況,我們可以在利用了z之後刪除z,而那些沒法再利用的,也就是z*x大於1000,000的就直接從鏈表中刪除

 

還有注意一點就是int溢出,所以我們可以定義一個int64的變數存相乘的值

 

模版代碼:注釋部分是我測試的演算法複雜度,對於求1000,000以內的素數,只用了120,0000步

#include<stdio.h>
#include<string.h>
#define MAX 1000000
typedef __int64 LL;

struct List
{
 List *last;
 int value;
 List *next;
};

bool isPrime[MAX + 1];

List* where[MAX + 1];

int isResult[MAX + 1];

int init()
{
 int i;
 LL temp, temp1;
 List *p;
 List *p1;
 List *q1;
 List *head;
// int step = 0;                                              //測試用了多少步

 memset(isPrime, 0, sizeof(isPrime));

 for(i = 2; i <= MAX; i ++)
 {
  p = new List;
  where[i] = p;
  if(i == 2)
  {
   p -> last = NULL;
   p -> value = i;
   p -> next = NULL;
   head = p;
  }
  else
  {
   p -> last = where[i - 1];
   where[i - 1] -> next = p;

   p -> value = i;
   p -> next = NULL;
  }
 }

 for(i = 2; i <= MAX; i++)
 {
  if(isPrime[i])
   continue;
  else
  {
   for(p = head; p != NULL; p = p -> next)
   {
//    step ++;//測試用了多少步
    temp = i * (LL)(p -> value);
    if(isPrime[p -> value] && where[p -> value] != NULL)
    {
     temp1 = p -> value;
     p1 = where[temp1] -> last;
     q1 = where[temp1] -> next;

     p1 -> next = q1;
     if(q1 != NULL)
      q1 -> last = p1;

     delete where[temp1];
     where[temp1] = NULL;
     p = p1;
    }
    if(temp > MAX)
     break;
    if(!isPrime[temp])
    {
     isPrime[temp] = 1;
     if(temp * i > MAX)
     {
      p1 = where[temp] -> last;
      q1 = where[temp] -> next;
      delete where[temp];
      where[temp] = NULL;

      p1 -> next = q1;
      if(q1 != NULL)
       q1 -> last = p1;
     }

    }
    
   }
  }
 }

// printf("%d\n", step);//測試用了多少步

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.