前提:作为一名只工作两三年的phper菜鸟且今天第一次写博客,有什么不足或者问题请多多见谅,也欢迎指正。
最近面试遇到了很多问题,本来还自信心满满的我惨遭打脸,这此的问题就是关于素数的,他的问题很简单:如何找出1-100以内的素数?
我想的很简单 详见代码 function getPrime($number){ $result = []; for ($a = 2;$a < $number;$a++){ if($a < 10){ if($a % 4 <> 0 && $a % 6 <> 0 && $a % 9 <> 0){ $result[] = $a; } }else{ if($a % 2 <> 0 && $a % 3 <> 0 && $a % 5 <> 0 && $a % 7 <> 0){ $result[] = $a; } } } return $result; }但是他接下来就问哪1000以内呢?我第一个想到的就是试除法,具体的就是两个循环嵌套,代码如下:
function getPrime($number){ $prime = []; for ($a = 2; $a <= $number; $a++) { $flag = 0; //用于做个标识 //循环判断 for ($b = 2; $b < $a; $b++) { if ($a % $b == 0) { $flag = 1; break; } } if ($flag == 0 && $a != 1) {//1不是素数 $prime[] = $a; } } return $prime; }我很快把这个方案给否决掉了,运算量太大,也太耗时间了,又有点紧张,一时间没有想到很好的解决办法。只有大概一个思路,就是排除法,在给定的集合中我把2的倍数,3的倍数依次剔除,那么剩下的不就是素数了,于是后面我又想了几套解决方案,代码如下:
function two($number){ if($number < 10){ return false; } $min = floor(sqrt($number));//相比较上面加了这么一步,就是所传范围的最大值开跟,即查找这个条件($a % 2 <> 0 && $a % 3 <> 0 && $a % 5 <> 0 && $a % 7 <> 0) $prime = []; for ($a = 2; $a <= $min; $a++) { $flag = 0; //用于做个标识 for ($b = 2; $b < $a; $b++) { if ($a % $b == 0) { $flag = 1; break; } } if ($flag == 0 && $a != 1) { $prime[] = $a; } } return $prime; } //获取质数 function number($number){ $prime = two($number); $result = $prime; for($a = 2;$a < $number;$a++){ foreach ($prime as $v){ if($a % $v == 0){ break; }else{ if($v == end($prime)){ $result[] = $a; } } } } return $result; } 这种方式比试除法快了很多,经测试一千万范围花了26秒左右,应该还是有优化空间的。那么有没有比这个更快的,有,其实就是我面试大概想出的那个思路,排除法,代码如下:
function getPrime($number){ $arr=primeArr($number); $n = $number - 1;//素数个数,排除法 for ($i = 2;$i <= $number;$i++){ foreach ($arr as $v){ if($i % $v == 0){ $n--; break; } } } echo $n+count($arr); } /** * 下一个素数 */ function nextPrime($i){//下一个质数 while (true){ $i++; if($i == 2){ return $i; }elseif ($i < 2){ continue; } $is=true; for($j = 2;$j <= sqrt($i);$j++){ if($i % $j == 0){ $is = false; } } if($is){ return $i; } } } /** * 作为除数的素数数组 */ function primeArr($a){ if($a <= 1){ return []; } $arr = []; $prime=0; while ($prime <= sqrt($a)){ $prime = nextPrime($prime); $arr[] = $prime; } return $arr; } 这个就更快了一千万的数据只需要10秒左右。我感觉作为普通的开发人员为什么会觉的进入瓶颈什么的,其实就是我们不愿意在细小的环节上多下功夫,大家都愿意偷懒,尤其对于什么外包公司,但是一旦思维形成惯势,再想纠正就很难了。还是希望大家包括我在这方面多下点功夫。