JS中数字是否为回文的最佳验证

Optimal verification if a number is Palindrom in JS

过去几天我遇到了一个问题。

我想写一个最佳的(在 JS 中)程序来验证一个数字是否是回文。

我目前的做法:

function isPalidrom2(pali){
//MOST time consuming call - I am splitting the digit into char array. 
  var digits = (""+pali).split("");
//To get the length of it. 
  var size = digits.length;
  var isPali = true;
  for(var i = 0; i<Math.floor(size/2); i++){
    //I am comparing digits (first vs last, second vs last-1, etc.) one by one, if ANY of the pars is not correct I am breaking the loop. 
    if(parseInt(digits[i]) != parseInt(digits[size-i-1])){
      isPali = false;
      break;
    }
  }
  return isPali;
}

这不是最佳选择。我最浪费的时间是从 INT 到 STRING 的变化。

我没主意了 - 我试图理解 BIT 运算符,但我做不到。 - 我试图 google 并寻找替代方法 - 但我找不到任何东西。 - 我尝试使用不同的算法 - 但这个算法是我能够应用的最快的。

简而言之 - 我的问题是: "how can I make it faster?"

编辑:

所以我要解决的任务:

Find all of the prime numbers within the range of all five digit numbers. Among all of the multiplies (i*j) they are between them, find the most significant palindrome.

我目前的做法:

function isPrime(number){
  var prime = true;
  var i
  for(i = 2; i<= number/2; i++){
if((number%i)==0){
  prime = false;
  break;
}
  }
  return prime;
}

function get5DigitPrimeNr(){
  var a5DigitsPrime = [];
  var i;
  for(i = 10000; i<100000; i++){
if(isPrime(i)){
  a5DigitsPrime.push(i)
}
  }
  return a5DigitsPrime;
}

function isPalidrom(pali){
  var digits = (""+pali).split("");
  //we check if first and last are the same - if true, we can progress
  size = digits.length;
  return
(digits[0]==digits[size-1]) &&
(parseInt(digits.slice(1, Math.floor(size/2)).join("")) ==
  parseInt(digits.reverse().slice(1, Math.floor(size/2)).join("")))
}

function isPalidrom2_48s(str) {
  var str = str.toString();
  const lower = str.substr(0, Math.floor(str.length / 2));
  const upper = str.substr(Math.ceil(str.length / 2));
  return lower.split("").reverse().join("") === upper;
}

function isPalidrom_22s(pali){
  var digits = (""+pali).split("");
  var size = digits.length;
  for(var i = 0; i<Math.floor(size/2); i++){
//console.log("I am comparing: "+i+", and "+(size-i-1)+" elements in array")
//console.log("I am comparing digit: "+digits[i]+", and "+digits[(size-i-1)]+"")
if(digits[i] !== digits[size-i-1]){
  //console.log('nie sa rowne, koniec')
  return false;
}
  }
  return true;
}

function isPalidrom2_80s(pali){
  return parseInt(pali) == parseInt((""+pali).split("").reverse().join(""))
}

function runme(){
  var prime5digits = get5DigitPrimeNr();
  var size = prime5digits.length;
  var max = 0;
  var message = "";
  for(var i = 0; i<size; i++){
for(var j = 0; j<size; j++){
  var nr = prime5digits[i]*prime5digits[j];
  if(nr>max && isPalidrom2(nr)){
    max = nr;
    message = 'biggest palidrome nr: '+nr+', made from numbers: '+prime5digits[i]+' x '+prime5digits[j];
  }
}
  }
  console.log(message)
}

function timeMe(){
  var t0 = performance.now();
  runme();
  var t1 = performance.now();
  console.log("Function took " + millisToMinutesAndSeconds(t1 - t0) + " s to find the perfect palindrom.")
}

//helper functons:

function millisToMinutesAndSeconds(millis) {
  var minutes = Math.floor(millis / 60000);
  var seconds = ((millis % 60000) / 1000).toFixed(0);
  return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
}

最快的可能是依赖javascript原生方法:

 function isPalindrome(str) {
   const lower = str.substr(0, Math.floor(str.length / 2));
   const upper = str.substr(Math.ceil(str.length / 2));

   return lower.split("").reverse().join("") === upper;
}

或者从您的代码中删除所有不必要的对话:

function isPlaindrome(str) {
  const half = str.length / 2;
  for(var i = 0; i < half; i++)
    if(str[i] !== str[str.length - i - 1])
       return false;
  return true;
}

为了保持代码的精神,您可以使用 return 而不是 break 退出循环并直接使用字符串而不转换为数组。作为数组,字符串可以通过索引访问单个字符。

function isPalidrom2(value) {
    var digits = value.toString(),
        length = digits.length,
        i, l;

    for (i = 0, l = length >> 1; i < l; i++) {
        if (digits[i] !== digits[length - i - 1]) {
            return false;
       }
    }
    return true;
}

console.log(isPalidrom2(1));
console.log(isPalidrom2(12));
console.log(isPalidrom2(1221));
console.log(isPalidrom2(123));

如果您想加快速度,可以通过优化 isPrime(n) 函数来再缩短几秒钟。

  • 您不需要检查每个因子,只检查小于 sqrt(n)
  • 的素因子
  • 如果你按升序检查从 2 到 99999 的每个数字,你可以随时存储结果,所以你不需要不断地重新计算之前的素数列表

像这样:

var savedPrimes = [2]

function isPrime(n){
    // call this method with increasing values of n (starting at 2), saving primes as we go,
    // so we can safely assume that savedPrimes contains all primes less than n
    for(var i=0; i<savedPrimes.length; i++)
    {
        var f = savedPrimes[i];
        if ((n % f) == 0)
            return false; // found a factor
        if (f*f>=n)
            break; // stop checking after f >= sqrt(n)
    }
    // no prime factors - we found a new prime
    savedPrimes.push(n);
    return true;
}


function get5DigitPrimeNr(){
    var a5DigitsPrime = [];
    var i;

    // first find all the primes less than 10000
    for(i = 3; i<10000; i++){
        isPrime(i);
    }

    // now find (and keep) the rest of the primes up to 99999
    for(i = 10000; i<100000; i++){
        if(isPrime(i)){
            a5DigitsPrime.push(i)
        }
    }
    return a5DigitsPrime;
}

EDIT - 当我用这种方法 运行 你的代码时,我得到的时间是 10 秒

代码:

您可以使用多种方法(不知道它们是否最佳):

Palindrom = _ => (_=''+_) === [..._].sort(_=>1).join``

还有一些:

let isPalindrome = __ => (_=(__=__+'').length)==0||_==1?!0:__[0]==__.slice(-1)?isPalindrome(__.slice(1,-1)):!1

let isPalindrome = (s,i) => (i=i||0)<0||i>=(s=''+s).length>>1||s[i]==s[s.length-1-i]&&isPalindrome(s,++i);

let isPalindrome = (str) => {
  var len = ~~((str=str+'').length / 2);
  for (var i = 0; i < len; i++)
    if (str[i] !== str[str.length - i - 1])
      return false;
  return true;
}

Updated 现在将数字作为输入