【问题标题】:Largest palindrome product in JavascriptJavascript 中最大的回文乘积
【发布时间】:2013-09-17 06:38:24
【问题描述】:

回文数的两种读法相同。由两个 2 位数字的乘积构成的最大回文数是 9009 = 91 × 99。

找出由两个 3 位数字相乘的最大回文数。

我编写了这段代码来找到解决方案,但 Project Euler 网站上的答案仍然不正确:

function Palindromic(x) {
    var pal = parseInt(x.toString().split('').reverse().join(''));

    if (pal === x)
        return true;
    else
        return false;
}

var x = 100,
    y = 100,
    product = x * y;

for (x; x <= 999; x++) {
    for (y = x; y <= 999; y++) {
        product = x * y;
        if (Palindromic(product)) {
            console.log(x + '*' + y + '=' + product);
        }
    }
}

我的代码有问题吗?! 无论如何,我得到的答案是 888888 from 924*962

【问题讨论】:

  • 如果我们知道正确答案应该是什么会有所帮助。
  • 如果您正在寻找最大回文数,为什么不反向循环?

标签: javascript math for-loop


【解决方案1】:

我不认为,您的代码存在真正的问题。您只是不过滤最大的产品,这不一定是您的最后一个输出。只需为最大的产品添加额外的检查,例如像这样:

var x, y, product, max = 0;

for (x = 100; x <= 999; x++) {
    for (y = x; y <= 999; y++) {
        product = x * y;
        if (Palindromic(product)) {
          if( max < product ) { // this is new
            max = product;
            console.log(x + '*' + y + '=' + product);
          }
        }
    }
}

返回

913*993=906609

作为最大的结果。

【讨论】:

  • 谢谢@Sirko,他很有帮助
【解决方案2】:

很晚的答案,我的方法类似于Sirko。我发现了一种我认为可以显着提升性能的有趣方法,所以我想分享一下:

function isPalindrome(num) {
  return parseInt(String(num).split('').reverse().join('')) === num;
}

function findLargestPalindromeProduct(numberOfDigits) {
  var start = Math.pow(10, numberOfDigits - 1);
  var end = Math.pow(10, numberOfDigits);
  var largestPalindrome = 0;
  var product;
  for (a = start; a < end; a++) {
    for (b = start; b < end; b++) {
      product = a * b;
      if (largestPalindrome < product) {
        if (isPalindrome(product)) {
          largestPalindrome = product;
        }
      }
    }
  }

  return largestPalindrome;
}
console.time('Function #1');
for (var i = 0; i < 100; i++) {
  findLargestPalindromeProduct(3);
};
console.timeEnd('Function #1')

当我在 Chrome 控制台中运行它时,每次迭代的平均时间约为 34 毫秒。

当我首先检查它是否是回文时,我的平均迭代时间约为 500 毫秒。

之所以这么快的原因是因为检查乘积是否大于最大回文数是非常快的检查并快速过滤掉许多对,而不是先检查它是否是回文数(当它甚至可能不会比最大的回文大 - 即使它 实际上是一个回文)。

【讨论】:

    【解决方案3】:
    let string = [];
    let mul = 0;
    
    let x = 100;
    while(x < 1000){
        for(y = 100; y < 1000; y++){
            mul = x * y;
            let n = mul.toString();                   //to convert multiplied value to string 
            let stringSplit = n.split("");            //splits the string in array
            let reverseSplit = stringSplit.reverse(); //reverse the string array
            let joinSplit = reverseSplit.join("");    //join the reversed array into string
            if (joinSplit == n){          //check weather reversed string is equal to multiplied value
                string.push(joinSplit);  //as there are lots of value it puts them in array
            }
        }
      x++;
     }
     string.sort(function(a, b){return b-a}); // sort array in descending order as we want highest value 
     console.log(string[0]); 
    

    【讨论】:

    • 没有解释这个答案是有限的使用。请说明您的解决方案为何有效。
    • 感谢您告诉我我的错误。其实我刚开始编程我不知道添加评论的好主意,但我试过了
    【解决方案4】:

    也是一个迟到的答案,但遍历所有选项真的很慢。您可以循环批次,对于 n===2,您可以批次 10,对于 n ===3 批次,每批次 100 等等

    这是一个 JSPerf https://jsperf.com/largest-palindrome-product/1

    export const isPalindrome = (arg: string | number): boolean => {
      const orig = `${arg}`;
      const reverse = orig.split("").reverse().join("");
    
      return orig === reverse;
    };
    
    /**
     * The idea here is to search in batches to avoid looping trough all of the possibilities.
     *
     * For n === 2 you will first search between 90 and 99 if no palindrome found you will move to 80 and 89 etc.
     * If a palindrome is found you will pick the max from the batch
     *
     */
    export const largestPalindromeProduct = (num: number): [number, [number, number]] => {
      const min = Number("1".padEnd(num, "0"));
      const max = Number("9".padEnd(num, "9"));
    
      let stepperMax = max;
      let res: number = 0;
    
      let position: [number, number] = [min, min];
    
      while (stepperMax >= min) {
        for (let i = max; i >= stepperMax - min - 1; i--) {
          for (let j = max; j >= stepperMax - min - 1; j--) {
            const temp = i * j;
            if (isPalindrome(temp) && temp > res) {
              position = [i, j];
              res = temp;
            }
          }
        }
    
        if (res !== 0) {
          return [res, position];
        }
    
        stepperMax = stepperMax - min - 1;
      }
    
      return [res, position];
    };

    【讨论】:

      【解决方案5】:

      为了更有可能尽早找到大回文数,您可以从范围的最后一个数字向下计数,而不是从范围的第一个数字向上计数。

      通过这种方式,您可以停止检查那些太小而无法改进迄今为止发现的最大回文的因素,尽早打破内循环。

      例如:

      /**
       * Check if a number is a palindrome.
       * @param {number} num Number to be checked.
       * @returns {boolean} True if the number is a palindrome, false otherwise.
       */
      const isPalindrome = (num) => {
        const numStr = String(num)
        const reverseNumStr = [...numStr].reverse().join('')
        return numStr === reverseNumStr
      }
      
      /**
       * Find the largest palindrome product of two n-digit numbers.
       * @param {number} digits Number of digits of the multiplied numbers.
       * @returns {number} Largest palindrome product.
       */
      const largestPalindromeProduct = (digits) => {
        const start = 10 ** (digits - 1) // first n-digit number
        const end = (10 ** digits) - 1 // last n-digit number
        let max = 0
      
        for (let factorA = end; factorA >= start; factorA--) {
          for (let factorB = end; factorB >= factorA; factorB--) {
            const product = factorA * factorB
            if (product <= max) break
            if (isPalindrome(product)) max = product
          }
        }
      
        return max
      }
      

      官方的 Project Euler 问题 4 概述涵盖了此优化和其他优化。

      【讨论】:

        【解决方案6】:

        这是一个很晚的答案,但是我提出了一种不同的方法,它是一个足够的解决方案,而不是完美的解决方案

        我只检查了 6 位回文。

        1.从最大值只生成6位回文数(前三位,后三位应取反)

        2.检查生成的回文数字是否有两个3位数字作为因子,如果有则返回数字,即两个3位数字乘积所能产生的最大回文数。 c#中的代码示例。

            static void Main(string[] args)
            {
                Console.WriteLine(SixDigitPalindromeWithDivisor().ToString());
                Console.ReadLine();
            }
        
            public static int SixDigitPalindromeWithDivisor()
            {
                for (int i = 999; i > 100; i--)
                {
                    //generating palindrome number from max
                    var palindromeInt = Int32.Parse(Convert.ToString(i) + ReverseString(Convert.ToString(i)));
        
                    //checking three digit number factor exist
                    if (CheckThreeDigitDivisorExists(palindromeInt))
                    {
                        return palindromeInt;
                    }
                }
                return 0;
            }
        
            public static bool CheckThreeDigitDivisorExists(int number)
            {
                for (int i = 999; i > 100; i--)
                {
                    if (number % i == 0)
                    {
                        if (number / i <= 999)
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
        
            public static string ReverseString(string s)
            {
                char[] arr = s.ToCharArray();
                Array.Reverse(arr);
                return new string(arr);
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-01-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多