找到由两个3位数字的产品制成的最大的回文 - Javascript

时间:2014-01-22 15:21:07

标签: javascript

任何人都可以告诉我代码有什么问题。找到由两个3位数字的乘积制成的最大palindrome

function largestPalindrome(){

    for(var i =999; i>100; i--){
        for(var j = 999; j>100; j--){
            var mul = j*i;
            if(isPalin(mul)){
                return i * j;
            }
        }
    }
}

function isPalin(i){
    return i.toString() == i.toString().split("").reverse().join("");
}

console.log(largestPalindrome());

This answer was close to my question 但我仍然觉得我在做循环的方式它应该会给我带来最大的产品。

21 个答案:

答案 0 :(得分:23)

你的工作不正常,因为它检查999*999,然后是999*998,然后是999*997,直到它达到999*583左右。虽然它没有检查997*995或更接近顶部的东西 这会产生更大的数字

function largestPalindrome(){

    var arr = [];    
    for(var i =999; i>100; i--){
        for(var j = 999; j>100; j--){
            var mul = j*i;
            if(isPalin(mul)){
                arr.push(j * i);
            }
        }
    }

    return Math.max.apply(Math, arr);
}

function isPalin(i){
    return i.toString() == i.toString().split("").reverse().join("");
}

console.log(largestPalindrome());

这是另一种方法,将3个数字生成的所有palindrome存储在一个数组中,然后使用Math.max on the array获取最大的palindrome

答案 1 :(得分:18)

我认为如果你将数学应用于问题,你可以真正减少猜测。

我会将三位数字写为1000 - a1000 - b,这意味着回文为1 000 000 - 1000(a+b) + ab

首先,让我们找到ab < 1000的解决方案。然后,最左边的三个数字是1000 - (a+b),最右边的三个数字是ab

然后我会说这是一个数字为x,y,z的回文:

100x+10y+z=ab
100z+10y+x=1000-a-b

从而

99x-99z = ab+a+b-1000
x-z = 1/99(ab+a+b-10)-10

那么(ab + a + b-10)可以被99整除,我们也知道x和z是左边的数字在-9和0之间(整个shebang是对称的,所以我们可以假设x&lt; = z)所以1/99(ab+a+b-10)介于1和9之间。我们可以将ab+a+b-10重写为ab+a+b+1-11=99p所以(a+1)(b+1)=99p+11=11*(9p+1)其中p在1到9之间运行。这真的是真的易:

for ($p = 1; $p <= 9; $p++) {
  $n = 9 * $p + 1;
  // This could be vastly optimized further.
  for ($j = 1; $j <= $n; $j++) {
    if ($n % $j === 0) {
      $a = 1001 - $n / $j;
      $b = 1001 - 11 * $j;
      $test = $a * $b;
      if (strrev($test) === (string) $test) {
        print "$a $b " . $a * $b . "\n";
      }
    }
  }
}

现在只打印一个正确的解决方案。

现在我们知道906609是一个解决方案,因此有一个解决方案,其中ab> 1000和1000(a + b) - ab&lt; 93391?没有:))

答案 2 :(得分:8)

如@ VisioN的评论所述:

995*583 = 580085是一个回文。

993*913 = 906609也是(较大的)回文。

您的代码会在995*583之前检查993*913并在找到的第一个回文中退出,因此它不会返回最大的回文。

解决方案:从999*999 = 998001开始向下获取最大的回文并检查它们是否可以写为xyz*abc

或者只是使用您链接的问题中的已接受解决方案:)。您的解决方案,但是当您找到第一个回文时,不要返回,检查它是否大于已找到的最大回文,在这种情况下您需要更换它。一旦最大的回文大于i*999,您就可以停止。

答案 3 :(得分:5)

包含评论的更优化版本。请注意,不需要快速返回,只需存储max并优化周期,以便在j*i已经过检查时不重新计算i*j

function largestPalindrome() {

    var max = 0;

    // not using i >= 100 since 100*100 is not palindrome! :)
    for (var i = 999; i > 100; i--) {
        // because i * j === j * i, no need of both i and j
        // to count down from 999
        for (var j = i; j > 100; j--) {
            var mul = j * i;
            if (isPalin(mul) && mul > max) {
                max = i * j;
            }
        }
    }

    return max;

}

function isPalin(i) {

    // adding empty string to i instead using of .toString
    // avoids unnecessary wrapping in String object on the left side
    i = '' + i;

    // don't rely on ==,  use === instead
    return i === i.split("").reverse().join("");

}

console.log(largestPalindrome());

答案 4 :(得分:4)

使用underscore.js建议解决方案。首先,找到所有的回文,然后从最大的回文中循环,然后返回有两个3位素因子的回文。

function isPalindrome(num) {
    var str = num.toString();
    return str.split('').reverse().join('') === str;
}

function palindromes() {
    var max = 999 * 999;
    var min = 100 * 100;
    return _.select(_.range(max, min, -1), isPalindrome);
}

palindromes().find(function (x) {
    if (_.find(_.range(999, 100, -1), function (y) {
        return (x % y === 0 && y != x / y && x / y < 1000) ? true : false;
    })) return true;
})

答案 5 :(得分:3)

#define MAX(a, b) ((a) > (b) ? (a) : (b))
int largestPalindrome()
{
    int ret = 0;
    for (int i = 999; i > 100; --i)
    {
        int jLimit = MAX(ret / i, 100);
        for (int j = i; j > jLimit; --j)
        {
            int ans = i * j;
            if (isPalin(ans))
            {
                ret = MAX(ans, ret);
            }
        }
    }

    return ret;
}

上面解释的原因。

当我们找到回文产品时,我们可以重新计算j的范围。这应该更快。

答案 6 :(得分:3)

上述解决方案将完美无缺,但当我们试图找出这2个数字(i = 913和j = 993)时,我们将会发出 ONLY

我将修改Azder提出的解决方案

int max = 0;
int no1 = 0;
int no2 = 0;

// not using i >= 100 since 100*100 is not palindrome! :)
for (var i = 999; i > 100; i--) {
    // because i * j === j * i, no need of both i and j
    // to count down from 999
    for (var j = i; j > 100; j--) {
        var mul = j * i;
        if (isPalin(mul)) {
            if ((i+j) > max) {
               max = i+j;
               no1 = i; no2 = j;
            }
        }
    }
}

//Now we can get the 2 numbers (no1=993 and no2=913)

return (no1*no2);

答案 7 :(得分:2)

我认为您可以使用此链接提供的代码 http://www.mathblog.dk/project-euler-problem-4/

因为这样可以节省乘法的CPU周期,这是非常昂贵的操作。

即使在这个你可以做更多的东西使其更像,你可以稍微修改它的while循环

out.write("TstMsg"+ "\n")

因此,我们可以将其写为while (!found) { firstHalf--; palin = makePalindrome(firstHalf); for (int i = 999; i > 99; i--) { if ((palin / i) > 999 || i*i < palin) { break; } if ((palin % i == 0)) { found = true; factors[0] = palin / i; factors[1] = i; break; } } } ,而不是从i=999 : 100,移动,因为您可以在其平方根中找到数字因子。请参阅链接How to find Number is prime number or not!

此外,您可以将i=sqrt(palin):100更改为if(condition),因为与零相比,通常不会将其视为一种好的做法。与简单的否定位相比,需要更多的CPU周期。

答案 8 :(得分:2)

这就是我做的。我用老式的方式来检查回文。它似乎在我的电脑上运行得更快,但我可能错了。像上面的帖子一样推送到一个阵列,在我的电脑上肯定是非常慢的。控制台明显滞后。我建议只检查你的产品是否大于你当前的最大值,如果是,存储它而不是把所有东西都推到一个阵列。如果我错了,请随时纠正我。非常感谢。

//should find the largest palindrome made from the product of two 3 digit numbers
var largestPalindrome = function() {

    var max = 0,
        product = 0;
    for (var num1 = 999; num1 >= 100; num1--) {
        for (var num2 = 999; num2 >= 100; num2--) {
            product = num1 * num2;
            product > max && isPalindrome(product.toString()) ?  max = product : 0;
        }
    }
    return max;
};

//check to see if product is a palindrome
var isPalindrome = function(product) {
    var palindromeCheck = true;
    for (var i = 0; i < product.length / 2; i++) {
        if (product[i] != product[product.length - i - 1])
            palindromeCheck = false;
    }
    return palindromeCheck;

   //return product === product.split("").reverse().join("");
};

答案 9 :(得分:1)

而不是创建ArrayArrayList来存储所有回文,我只创建了另一个变量max,并在其中存储了最高价值的回文。

我的代码是Java代码,但您可以从中理解逻辑。 这是我的代码,以更好地解释我所说的内容(阅读评论):

package euler;
import java.util.ArrayList; import java.util.Collections;

public class Problem4 {
    public static void main (String[] args)
    {
        int product=0;
            int max=0;
        for(int i=999;i>100;i--)
        {
            for (int j=i;j>100;j--)
            {
                product=i*j;

                if(isPalindrome(product))
                {
                    //Just store maximum value of product.
                    //Following if loop is required in your code,in place of return i*j;
                                    if(product>max)
                        { max=product; }
                }
            }
        }
        System.out.println(max);    
    }
    //might be inefficient to create StringBuilder and again String to compare.
    public static boolean isPalindrome(int product)
    {
        boolean isPalindrome=false;
        StringBuilder temp = new StringBuilder(Integer.toString(product)).reverse();
        if(temp.toString().equals(Integer.toString(product)))
        {
            isPalindrome=true;
        }
        return isPalindrome;
    }
}

当你得到第一个回文时,你正在做的是返回并退出循环。在你的情况下,它不是最大值回文。

而是使用if条件并跟踪最大值并让循环继续直到结束。

我添加了if条件,让循环运行并注册该值。

从此代码中得到了正确的答案。

PS。谢谢你的意见。我想我可以在第一时间更好地解释它。

答案 10 :(得分:1)

我已经看到很多关于这个问题的帖子,这是我提出的解决方案:

  • 两个3位数的倍数的最小数字是10000(100 * 100)
  • 两个3位数的倍数的最大数字是998001(999 * 999)

我们的回文位于这两个数字之间,写一个程序循环遍历这些数字,每当你得到回文检查它是否可以被3位数字完全整除,商也是3位数。

下面是我在C#中的程序,它打印的最后一个数字是我们要求的答案,享受。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections;

namespace E
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //Your code goes here
            for(int i=10000;i<=998001;i++)
            {
                string s1 = i.ToString();
                char[] array = s1.ToCharArray();
                Array.Reverse(array);
                string s2 = new String(array);
                if(s1==s2)
                {

                    for(int j=100;j<=999;j++)
                    {
                        if(i%j==0 && i/j <= 999)
                        {
                            System.Console.WriteLine(i);        
                            continue;
                        }
                    }
                }
            }
            System.Console.WriteLine("done");
        }
    }
}

答案 11 :(得分:1)

我认为这应该是最佳的

#include <functional>
#include <algorithm>
#include <iostream>
using namespace std;
template <typename T>
bool IsPalindrome(const T num) {
    T reverse = 0;
    T n = num;
    while (n > 0) {
        reverse = (reverse * 10) + n % 10;
        n /= 10;
    }
    return reverse == num;
}


template <typename T = long long int>
T LongestPalindromeFromProductOfNDigitNums(int n) {
    T result = 0, val = 0, max_n_digit_num = std::pow(10, n)-1,
    least_n_digit_num = std::pow(10, n-1);
    int n_checks = 0;
    for (T i = max_n_digit_num; i >= least_n_digit_num; --i) {
        if ((i*i) < result) {//found the highest palindrome
            break;
        }
        for (T j = i; j >= least_n_digit_num; --j) {
            val = i*j;
            ++n_checks;
            if (val < result) // any product i*j for the value of 'j' after this will be less than result
                break;
            if (IsPalindrome(val)) {
                if (val > result)
                    result = val;
                break;  // whenever a palindrome is found break since we only need highest one
            }
        }
    }
    std::cout << " Total num of checks = " << n_checks << std::endl;
    return result;
}

int main() {
    int n = 3;
    std::cout << " LongestPalindromeFromProductOfNDigitNums for n = "
    << n << " is " << LongestPalindromeFromProductOfNDigitNums(n) << std::endl;
    n = 4;
    std::cout << " LongestPalindromeFromProductOfNDigitNums for n = "
    << n << " is " << LongestPalindromeFromProductOfNDigitNums(n) << std::endl;
    return 0;
}

http://ideone.com/WoNSJP

答案 12 :(得分:1)

斯威夫特3:

// my approach is to make 6-digit palindrome first and then 
// check if I can divide it by 3-digit number 
// (you can see some visual listing at the end of the code)
// execution time on my laptop is around: 2.75409698486328 sec

import Foundation

func maxPalindrom() -> Int {

    var result = 999999
    var i = 9
    var j = 9
    var k = 9

    while true {
        while true {
            while true {
                print("in K loop: \(result) k = \(k)")

                if isDivisible(number: result) {
                    return result
                }
                if k <= 0 {
                    k = 9
                    result += 9900
                    break
                }
                result -= 1100
                k -= 1
            }

            print("in J loop: \(result)")
            if isDivisible(number: result) {
                return result
            }
            if j < 0 {
                j = 9
                result += 90090
                break
            }
            result -= 10010
            j -= 1
        }

        print("in I loop: \(result)")
        if isDivisible(number: result) {
            return result
        }
        if i < 0 {
            break
        }
        result -= 100001
        i -= 1
    }

    if result == 100001 {
        return -1
    }

    return -1
}


func isDivisible(number: Int) -> Bool {
    var i = 999

    while true {

        if number % i == 0 && number / i < 999 {
            return true
        }

        if i < 500 {
            return false
        }

        i -= 1
    }

}


let start = NSDate()
print(maxPalindrom())       // 906609
let end = NSDate()

print("executio time: \(end.timeIntervalSince(start as Date)) sec") // ~ execution time: 2.75409698486328 sec

//in K loop: 999999 k = 9
//in K loop: 998899 k = 8
//in K loop: 997799 k = 7
//in K loop: 996699 k = 6
//in K loop: 995599 k = 5
//in K loop: 994499 k = 4
//in K loop: 993399 k = 3
//in K loop: 992299 k = 2
//in K loop: 991199 k = 1
//in K loop: 990099 k = 0
//in J loop: 999999
//in K loop: 989989 k = 9
//in K loop: 988889 k = 8
//in K loop: 987789 k = 7
//in K loop: 986689 k = 6
//in K loop: 985589 k = 5
//in K loop: 984489 k = 4
//in K loop: 983389 k = 3
.....

答案 13 :(得分:1)

这里的大部分答案都是正确的。如果你想保存900 * 900循环,你可以循环遍历10000到998001之间的所有回文,并找出它们是否可被3位数整除。

 static void largestpalindromeproduct(){
   int a=999,b=999,c=a*b,loopcounter=0;
   while(c>10000){
       loopcounter++;
       c--;
       if(isPalindrome(c))
           if(isDivisible(c))
           break;
   }

   System.out.println(" largest : " + c+ "\nloops:"+ loopcounter);       
}
static boolean isDivisible(int n){
    int a=999;
    while(a>=100){
        if(n%a==0){
            if(secondDividerIs3Digit(n,a))
            return true;
        }
        a--;
    }
    return false;
}
static boolean secondDividerIs3Digit(int n, int a){
    Integer b=n/a;
    if(b.toString().length()==3)
        return true;
    return false;
}

static boolean isPalindrome(int n){
    Integer i=new Integer(n);
    String p=i.toString();
    StringBuffer s=new StringBuffer(i.toString());
    s.reverse();
    if(p.equals(s.toString()))
        return true;
    return false;
}

答案 14 :(得分:0)

作为一个非常简单的解决方案,这个解决方案

public class LargestPallendrome {

public static void main(String[] args) {

    int a = 999;
    int b = 999;

    long max = 0;

    while (a > 100) {
        long num = a * b;
        if (checkPallendrome(num)) {
            if (num > max)
                max = num;
        }
        if (b >= 100)
            b--;
        else {
            a--;
            b = 999;
        }
    }
    System.out.println(max);
}

public static boolean checkPallendrome(long num) {
    String a = num + "";
    String b = new StringBuffer(num + "").reverse().toString();
    if (a.equals(b))
        return true;
    return false;
}
}

答案 15 :(得分:0)

JavaScript中的另一个简单解决方案

function reverseNumber(n)
{
    n = n + "";
    return n.split("").reverse().join("");
}

function palindrom(){
 var r= 1 , y =1;
var largest = 0;
 while(r <= 1000){ 
   var num1 =  r;
   var num2 = 0;
 while(num1 <= 1000 && num2 <= num1){ 
        product = num1 * num2;
   if (product == reverseNumber(product)){
     console.log(`${num1} x ${num2} = ${product}`);
          if(product > largest){
            largest = product;
          }
   }
   num1 = num1 + 1;
   num2= num2 + 1;
}
r++;
}
console.log(``)
console.log(`The largest is ${largest}`);
}
console.log(palindrom());

答案 16 :(得分:0)

public static void main(String[] args) {
    int tempAns = 0;
    int max = 999;
    for (int i = 100; i <= max; i++) {
        for (int j = max; j >= i; j--) {
            if (findPalindrome(i * j) && (i * j) > tempAns) {
                System.out.println("Palindrome: " + j + " * " + i + " = " + j * i);
                tempAns = i * j;
            }
        }
    }
}

private static boolean findPalindrome(int n) {
    String nString = String.valueOf(n);
    int j = 0;
    int stringLength = nString.length() - 1;
    for (int i = stringLength; i >= 0; i--) {

        if (nString.charAt(j) == nString.charAt(i)) {

            if (i == 0) {
                return true;
            }
            j++;

        } else if (nString.charAt(j) != nString.charAt(i)) {
            return false;
        }

    }

    return false;
}

答案 17 :(得分:0)

这更好,因为它使用O(N)时间复杂度来查找所有回文(计算六位数no的回文是常数),而O(N 2 )几乎可以找到实际的回文回文中最糟糕的情况是,在找到第一个否定的那一刻,我们不必再进行任何计算,而实际上,我们正在对可能的回文号使用最坏的情况。所以我认为更好

package ProjectEuler;

import java.util.ArrayList;
import java.util.Arrays;

public class Largest_Palindrome_Product {

    public static void main(String[] args) {
        int count=0;
        for(int i=10000;i<998002;i++) {
            int x=i,c=0;
            while(x!=0) {
                c=c*10+x%10;
                x/=10;
            }
            if(c==i) {
            count++;
        }
        }
        int a[]=new int[count],count1=0;

    for(int i=10000;i<998002;i++) {
        int x=i,c=0;
        while(x!=0) {
            c=c*10+x%10;
            x/=10;
        }
        if(c==i) {
            a[count1]=i;
            count1++;
    }
    }
    Arrays.sort(a);
    tp:for(int i=count-1;i>=0;i--)
    {
        for(int j=999;j>100;j--)
            if(a[i]%j==0&&a[i]/j<=999) {
        System.out.println(a[i]+" "+j+" "+a[i]/j);
        break tp;
            }
    }
    }
}

答案 18 :(得分:0)

这就是我用Java语言编写的方式。简单容易!

let num1 = 999;
let num2 = 999;
let arr = [];

function check(x, y)
{
    if(String(x*y) == String(x*y).split("").reverse().join(""))
    {
        return true;
    }
return false;
}

for(let i=0; i<999999; i++)
{
    if(check(num1, num2))
    {
        arr.push(num1*num2);
        num1--;
        num2 = num1+1;
    }
num2--;
}

console.log(arr.sort((x, y) => y-x)[0]);

答案 19 :(得分:0)

我用random.randint检查过几次。在python 3.7.1中,应使用CMD运行它,并在20秒后会得到正确的答案。

import random
x,y,z,a,b=100,100,' ','',0
while 100<=x<=999 and 100<=y<=999:
    a=x*y
    x=random.randint(900,999)
    y=random.randint(900,999)
    print(x,' x ',y,'=')
    z=len(str(a))
    if z==6:
        if str(a)[0] == str(a)[5]:
            if str(a)[1] == str(a)[4]:
                if str(a)[2] == str(a)[3]:
                    print(a,'yes')
                    exit(a)
    else:
        pass
#906609

答案 20 :(得分:0)

可读选项:

function maxPalindrome(num) {
  let maxPalindrome = 1;

  for (let i = num; i > 0; i--) {
    for (let j = num; j > 0; j--) {
      const product = i * j;

      if (
        product.toString() === product.toString().split("").reverse().join("")
        && product > maxPalindrome
      ) {
        maxPalindrome = product;
      }
    }
  }

  return maxPalindrome;
}

console.log(maxPalindrome(999));