Javascript 编写一个JS函数来查找具有给定步长值的第一个素数对

Javascript 编写一个JS函数来查找具有给定步长值的第一个素数对,javascript,Javascript,**这是Codewars提出的问题 素数的间隔不是规则的。例如,从2到3,步骤为1。从3到5,步骤是2。从7点到11点是4点。在2到50之间,我们有以下两对2步素数: 3,5-5,7-11,13-17,19-29,31-41,43 我们将编写一个带有参数的函数步骤: g(整数>=2),表示我们要查找的步骤 m(整数>=2),它给出搜索的开始(包括m) n(整数>=m)表示搜索结束(包括n) 在上面的示例中,步骤(2,2,50)将返回[3,5],这是2和50之间具有2步的第一对 所以这个函数应该返

**这是Codewars提出的问题

素数的间隔不是规则的。例如,从2到3,步骤为1。从3到5,步骤是2。从7点到11点是4点。在2到50之间,我们有以下两对2步素数:

3,5-5,7-11,13-17,19-29,31-41,43

我们将编写一个带有参数的函数步骤:

g(整数>=2),表示我们要查找的步骤

m(整数>=2),它给出搜索的开始(包括m)

n(整数>=m)表示搜索结束(包括n)

在上面的示例中,步骤(2,2,50)将返回[3,5],这是2和50之间具有2步的第一对

所以这个函数应该返回两个素数的第一对,如果这些g步素数存在,则在极限m,n之间间隔g步,否则为nil或null或None或Nothing(取决于语言)

示例:

步骤(2,5,7)->[5,7]或(5,7)或{5,7}

步骤(2、5、5)->nil或null

步骤(4130200)->[163167]或(163167)或{163167}

这是我的解决方案——通过测试的时间太长了——我怎样才能使它更有效

    function step(g, m, n) {
  var arr = [];
  function isPrime(num){
    for (var k=2; k<num; k++){
      if(num%k ===0){
        return false;
      }
   }return true;
  }
  for (var i= m; i < n; i++){
    if(isPrime(i)=== true){
      arr.push(i);
    }
  }
  var endArr=[];
  for(var l=0;l<arr.length;l++)
  for(var p=1;p<arr.length;p++){
    if(arr[l]-arr[l-p]=== g){
      endArr.push(arr[l])
      endArr.push(arr[l]-g)
    }
  }
  return endArr.slice(0,2).sort(function(a,b){
    return a-b;
})

}
功能步骤(g、m、n){
var-arr=[];
函数isPrime(num){

对于(var k=2;k,这里有几个有趣的点

首先,您的
isPrime
实现效率低下。最快的方法是使用预缓存集(很容易准备一个),但即使没有预缓存集,您也只能通过将其除以素数来检查候选集,当下一个素数除数大于
sqrt(cand)
时退出

例如,如果您已经知道2、3、5和7是素数,您可以通过将
11
除以3(如
5>Math.sqrt(11)
)来检测
11
是素数哦,我有没有提到过您永远不会检查大于2的偶数

第二,您的实现尝试查找给定范围内的所有素数,然后尝试查找满足“差分条件”的所有素数。但是请记住,您的任务实际上是查找具有给定步骤的两个素数的第一对

记住这一点,为什么不检查一个数字(
n
),如果它是素数,尝试检查
n+g
的素数?您可以缓存该检查的结果,以便以后跳过它


这里有一种可能的方法:

function findPrimesByStep(g, m, n) {
  let primes = new Set([2]);

  function isPrimeNumber(candidate) {
    if (primes.has(candidate)) {
      return true;
    }

    let lim = Math.sqrt(candidate);
    for (let prime of primes) {
      if (prime > lim) {
        break;
      }

      if (candidate % prime === 0) {
        return false;
      }
    }

    primes.add(candidate);
    return true;
  }

  n = n - g;
  for (let i = 3; i <= n; i += 2) {
    let isPrime = isPrimeNumber(i);
    if (isPrime && i >= m && isPrimeNumber(i + g)) {
     return [i, i + g];
    }
  }

  return null;
}
函数findpromesbystep(g,m,n){
设素数=新集([2]);
函数isPrimeNumber(候选){
if(素数has(候选者)){
返回true;
}
设lim=Math.sqrt(候选者);
for(设素数的素数){
if(prime>lim){
打破
}
如果(候选%prime==0){
返回false;
}
}
素数。添加(候选);
返回true;
}
n=n-g;
对于(设i=3;i=m&&isPrimeNumber(i+g)){
返回[i,i+g];
}
}
返回null;
}

这是不完整且未优化的(它不检查琐碎的情况,它跳过2,不需要大于
sqrt(n)
)的素数),但显示了它是如何实现的。

您的
isPrime
函数很简单。您正在测试从2到k的每个数字。首先,唯一的偶数素数是2,因此测试4、6、8等是不必要的。您不必在
num
之前测试每个数字。相反,您可以在
sqrt(num)之后停止
。然后已经证明,所有大于2的素数的形式都是
6n-1或6n+1
。即
6*1-1=5
6*1+1=7
6*2-1=11
6*2+1=13
,等等。(不是所有的素数,但不是这种形式的数都不是素数).因为你看到的数字很小,你可以使用一个预先计算好的所有素数的表格,比如埃拉托什尼。