Этот метод значительно быстрее, чем предыдущие методы. Он начинается с оценки 999 * 999. Это реализация метода, предложенного в Puzzled над проблемой палиндромного произведения
Мы хотели бы попробовать более крупные продукты перед более мелкими, поэтому в следующий раз попробуйте 998 * 998, при этом внешний цикл каждый раз уменьшается на единицу. Во внутреннем цикле возьмите внешнее предельное число, чтобы создать (n+y)(n-y) (которое всегда меньше, чем n^2), перебирая y до тех пор, пока один из факторов не станет слишком большим или слишком маленьким.
Из https://pthree.org/2007/09/15/крупнейшее-палиндромное-число-в-питоне/, один из множителей должен быть кратен 11. Проверьте, не кратен ли один из множителей 11 и что произведение больше предыдущего найденное (или исходное) палиндромное число.
Как только эти тесты будут удовлетворены, проверьте, является ли произведение палиндромом.
Как только палиндром найден, мы можем увеличить предел внешнего цикла до квадратного корня из палиндрома, поскольку это минимальное значение, которое может быть ответом.
Этот алгоритм нашел ответ всего в 475 сравнениях. Это намного лучше, чем 810 000, предложенных простыми методами, или даже 405 450.
Может ли кто-нибудь предложить более быстрый метод?
Longest palindromes:
Max factor Max Palindrome
9999 99000099
99999 9966006699
999999 999000000999
9999999 99956644665999
99999999 9999000000009999
999999999 999900665566009999
public class LargestPalindromicNumberInRange {
private final long lowerLimit;
private final long upperLimit;
private long largestPalindrome;
private long largestFirstFactor;
private long largestSecondFactor;
private long loopCount;
private long answerCount;
public static void main(String[] args) {
long lowerLimit = 1000;
long upperLimit = 9999;
LargestPalindromicNumberInRange palindromicNumbers =
new LargestPalindromicNumberInRange(lowerLimit, upperLimit);
palindromicNumbers.TopDown();
}
private LargestPalindromicNumberInRange(long lowerLimit, long upperLimit){
this.lowerLimit = lowerLimit;
this.upperLimit = upperLimit;
}
private void TopDown() {
loopCount = 0;
answerCount = 0;
largestPalindrome = lowerLimit * lowerLimit;
long initialLargestPalindrome = largestPalindrome;
long lowerFactorLimit = lowerLimit;
for (long limit = upperLimit; limit > lowerFactorLimit; limit--){
for (long firstFactorValue = limit; firstFactorValue >= limit - 1; firstFactorValue--) {
long firstFactor = firstFactorValue;
long secondFactor = limit;
while(secondFactor <= upperLimit && firstFactor >= lowerLimit){
if (firstFactor % 11 == 0 || secondFactor % 11 == 0) {
long product = firstFactor * secondFactor;
if (product < largestPalindrome) { break; }
loopCount++;
if (IsPalindromic(product)) {
// System.out.print("Answer: " + product + "\n");
answerCount++;
largestPalindrome = product;
largestFirstFactor = firstFactor;
largestSecondFactor = secondFactor;
lowerFactorLimit = (long) Math.sqrt(largestPalindrome);
break;
}
}
firstFactor--;
secondFactor++;
}
}
System.out.print("Answer: " + largestPalindrome + "\n");
System.out.print("Factor1: " + largestFirstFactor + "\n");
System.out.print("Factor2: " + largestSecondFactor + "\n");
System.out.print("Loop count: " + loopCount + "\n");
System.out.print("Answer count: " + answerCount + "\n");
}
private boolean IsPalindromic(Long x) {
String forwardString = x.toString();
StringBuilder builder = new StringBuilder();
builder.append(forwardString);
builder = builder.reverse();
String reverseString = builder.toString();
return forwardString.equals(reverseString);
}
}
person
mturner
schedule
15.02.2018