LeetCode--素数(质数) Prime Number of Set Bits in Binary Representation

求某个数是否是素数(一个数只有两个因数1和它本身,则是素数。1不是素数):

 法一:暴力法

就是从2开始到n - 1依次判断,n % i == 0 则不是素数

法二:筛选  

一个数如果是合数,那么可以因式分解为两个数,一个大于等于sqrt(n), 另一个小于等于sqrt(n)

那么可以一直判断到sqrt(n)处,则省去sqrt(n) + 1 到 n - 1范围内的判断。

法三:

一个定理:大于等于5的素数,一定在6的倍数左右紧邻,5 7 11 13 17 19 23 29 31 37,但是和6的倍数紧邻的不一定就是质数,这个得进行判断

证明:令x≥1,将大于等于5的自然数表示如下:

······ 6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1 ······
可以看到,不在6的倍数两侧,即6x两侧的数为6x+2,6x+3,6x+4,由于2(3x+1),3(2x+1),2(3x+2),所以它们一定不是素数,再除去6x本身,显然,素数要出现只可能出现在6x的相邻两侧。这里有个题外话,关于孪生素数,有兴趣的道友可以再另行了解一下,由于与我们主题无关,暂且跳过。这里要注意的一点是,在6的倍数相邻两侧并不是一定就是质数。
此时判断质数可以6个为单元快进,即将循环中i++步长加大为6,加快判断速度,原因是,假如要判定的数为n,则n必定是6x-1或6x+1的形式,对于循环中6i-1,6i,6i+1,6i+2,6i+3,6i+4,其中如果n能被6i,6i+2,6i+4整除,则n至少得是一个偶数,但是6x-1或6x+1的形式明显是一个奇数,故不成立;另外,如果n能被6i+3整除,则n至少能被3整除,但是6x能被3整除,故6x-1或6x+1(即n)不可能被3整除,故不成立。综上,循环中只需要考虑6i-1和6i+1的情况,即循环的步长可以定为6,每次判断循环变量k和k+2的情况即可
 
public int isPrime(int num){
      //两个较小数另外处理   if(num == 1) return 0; if(num == 2 || num == 3) return 1;
      //不在6的倍数两侧的一定不是质数   if(num % 6 != 1 && num % 6 != 5) return 0; num = (int)Math.sqrt(num);
     //在6的倍数两侧的也可能不是质数   for(int i = 5; i < num; i+=6){ if(num % i == 0 || num %(i + 2) == 0){ return 0; } }
    //排除所有,剩余的是质数   return 1; }

  

 
法四:筛选法  求1 - N 内素数的个数
1.用一个N+ 1的boolean数组prime表示每个数,然后令奇数位置全部=false,偶数位置全部=true
2.然后进行判断,
   i=3; 由于prime[3]=true, 把prime[6], [9], [12], [15], [18], [21], [24], [27], [30]标为false.
     i=4; 由于prime[4]=false,不在继续筛法步骤。
     i=5; 由于prime[5]=true, 把prime[10],[15],[20],[25],[30]标为false.
     i=6>sqrt(30)算法结束。
 
 
(优化)法五:只表示奇数
1.用一个boolean数组prime,N/2大小,用来表示3,5,7,9,11,13,15,17,19......等的奇数(因为偶数不可能成为素数,2除外)
  均置为prime[i] = true
2.然后进行判断,
i = 0时,由于prime[0]=true(3); 则将数组内 i + (2 * i + 3) * j < sqrt(N) 的数置为false(为合数),  prime[3] = (9) prime[6] = (15), prime[9] = (21)...
i = 1时,prime[0]=true(5); 则将数组内 i + (2 * i + 3) * j < sqrt(N) 的数置为false(为合数), prime[6] = (15), prime[11] = (25)...
......
i = num时,由于 2 * i + 3 > sqrt(N),所以算法结束,返回为false的值即可
原文地址:https://www.cnblogs.com/SkyeAngel/p/9163271.html