最重要的因素

时间:2017-05-28 08:33:40

标签: javascript algorithm

我正在尝试完成algorithm challenge to find the largest prime factor of 600851475143。我不一定要求答案。只是想弄清楚为什么这段代码不起作用。为什么它会返回'undefined'而不是数字?

let isPrime = n => {
    let div = n - 1;
    while (div > 1) {
        if (n % div == 0) return false;
        div--;
    }
    return true;
};

let primeFactor = x => {
    for (let i = Math.floor(x / 2); i > 1; i--) {
        if (x % i == 0 && isPrime(i) == true) {
            return i;
        }
    }
};

console.log(primeFactor(35)); // 7
console.log(primeFactor(13195)); // 29
console.log(primeFactor(600851475143)); // undefined

2 个答案:

答案 0 :(得分:3)

问题不在于您的算法是完全有效的,请查看以下略有修改的算法,我所做的全部用您可以选择的参数替换您的起点Math.floor(x/2)



let isPrime = n => {
        let div = n - 1;
    while (div > 1) {
        if (n % div == 0) return false;
        div--;
    }
    return true;
};

function primeFactor(x, n){
    for (let i = n; i > 1; i--) {
        if (x % i == 0 && isPrime(i) == true) {
            return i;
        }
    }
}

console.log(primeFactor(35, 35));
console.log(primeFactor(13195, 13195));
console.log(primeFactor(600851475143, 100000))




使用上面的内容,您将得到一个证明您的实现有效的答案,但循环太大而无法完成整个事情(即来自Math.floor(600851475143/2))。假设您的计算机每秒可以进行5亿次循环,从300,425,737,571到1每个循环需要167小时,即使每秒50亿次循环也需要16个半小时。您的方法非常效率低,但返回正确的答案。您在JSBin上没有得到答案的原因更可能与浏览器/服务限制有关。

<小时/>

下更有效的解决方案的剧透

以下实现使用素筛(Sieve of Eratosthenes)来生成所请求的素数列表,然后检查它们是否完全考虑到给定数量,只要您使用足够大的素数列表,这将完全按预期工作。应该注意的是,因为它生成一个大的素数列表,如果运行不正确可能需要一些时间,应该生成单个素数列表并用于下面的所有调用,以及缓存的素数列表最终将通过以下方式执行较少的计算来获得回报:

&#13;
&#13;
function genPrimes(n){
  primes = new Uint32Array(n+1);
  primes.fill(1)
  for(var i = 2; i < Math.sqrt(n); i++){
    if(primes[i]){
      for(var j = 2*i; j < n; j+=i){
        primes[j] = 0;
      }
    }
  }
  primeVals = []
  for(var i = 2; i < primes.length; i++){
    if(primes[i]){
      primeVals.push(i);
    }
  }
  return primeVals;
}
    
function primeFactor(x, primes){
  var c = x < primes.length ? x : primes.length
  for (var i = c; i > 1; i--) {
    if(x % primes[i] == 0){
      return primes[i];
    }
  }
}

primes = genPrimes(15487457);
console.log(primeFactor(35, primes));
console.log(primeFactor(13195, primes));
console.log(primeFactor(600851475143, primes));
console.log(primeFactor(30974914,primes));
&#13;
&#13;
&#13;

答案 1 :(得分:2)

&#13;
&#13;
let primeFactor = x => {
    if (x === 1 || x === 2) {
        return x;
    }

    while (x % 2 === 0) {
        x /= 2;
    }
    
    if (x === 1) {
        return 2;
    }

    let max = 0;
    for (let i = 3; i <= Math.sqrt(x); i += 2) {
        while (x % i === 0) {
            x /= i;
            max = Math.max(i, max);
        }
    }

    if (x > 2) {
        max = Math.max(x, max);
    }
    
    return max;
};

console.log(primeFactor(35));
console.log(primeFactor(13195));
console.log(primeFactor(27));
console.log(primeFactor(1024));
console.log(primeFactor(30974914));
console.log(primeFactor(600851475143));
&#13;
&#13;
&#13;

优化

  • 将数字除以2,直到它为奇数,因为没有偶数是素数。

  • 迭代增量为2而不是1,以跳过所有偶数。

  • 迭代在sqrt(x)处停止。对此的解释是here