我正在尝试解决一个问题,要求找到最小的主要回文,这是在一个给定的数字之后,这意味着如果输入为24,则输出为101,因为它是24之后的最小数字,这两者都是素数和回文。
现在我的代码完全适用于小值但是当我插入像543212这样的东西作为输入时,我最终得到第20行的StackOverFlowError,然后是第24行的StackOverFlowErrors的多个实例。这是我的代码:
package nisarg;
import java.util.Scanner;
public class Chef_prime_palindromes {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
long num = input.nextLong();
isPalindrome(num + 1);
}
public static boolean isPrime(long num) {
long i;
for (i = 2; i < num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
public static void isPalindrome(long num) {
String word = Long.toString(num);
int i;
for (i = 0; i < word.length() / 2; i++) {
if (word.charAt(i) != word.charAt(word.length() - i - 1)) {
isPalindrome(num + 1);
}
}
if (i == word.length() / 2) {
if (isPrime(num)) {
System.out.println(num);
System.exit(0);
} else {
isPalindrome(num + 1);
}
}
}
}
答案 0 :(得分:2)
所有显示的现有解决方案都使用递归,并且存在这样的问题:在某些时候它们将达到StackOverflowException
将发生的点。
一个可并行化的更好的解决方案是将其改为循环。
可能是这样的:
package nisarg;
import java.math.BigInteger;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;
public class Chef_prime_palindromes {
private static final CopyOnWriteArrayList<BigInteger> PRIMESCACHE
= new CopyOnWriteArrayList<>();
public static void main(String[] args) {
try (Scanner input = new Scanner(System.in)) {
BigInteger num = new BigInteger(input.nextLine());
initPrimes(num);
for (num = num.add(BigInteger.ONE);
!isPrimePalindrome(num);
num = num.add(BigInteger.ONE));
System.out.println(num.toString());
}
}
private static void initPrimes(BigInteger upTo) {
BigInteger i;
for (i = new BigInteger("2"); i.compareTo(upTo) <= 0 ; i = i.add(BigInteger.ONE)) {
isPrime(i);
}
}
public static boolean isPrimePalindrome(BigInteger num) {
return isPrime(num) && isPalindrome(num);
}
// could be optimized
public static boolean isPrime(BigInteger num) {
for (int idx = PRIMESCACHE.size() - 1; idx >= 0; --idx) {
if (num.mod(PRIMESCACHE.get(idx)).compareTo(BigInteger.ZERO) == 0) {
return false;
}
}
if (!PRIMESCACHE.contains(num)) {
PRIMESCACHE.add(num);
}
return true;
}
public static boolean isPalindrome(BigInteger num) {
String word = num.toString();
int i;
for (i = 0; i < word.length() / 2; i++) {
if (word.charAt(i) != word.charAt(word.length() - i - 1)) {
return false;
}
}
return true;
}
}
答案 1 :(得分:1)
在每个递归调用中创建一个新的String object
并放置到堆栈(存储方法中创建的所有变量的位置,直到您离开该方法),这对于足够深的递归使得JVM到达结束时分配堆栈空间。
我通过将String对象放置在一个单独的方法中来改变它的局部性,从而减少其局部性并将其创建和销毁(释放堆栈空间)限制为一个递归调用。
package com.company;
import java.util.Scanner;
public class Chef_prime_palindromes {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
long num = input.nextLong();
isPalindrom(num + 1);
}
public static boolean isPrime(long num) {
long i;
for (i = 2; i < num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
private static void isPalindrom(long num) {
for (; ; ) {
if (isPalindrome(num)) {
if (isPrime(num)) {
System.out.println(num);
System.exit(0);
} else {
num++;
}
} else {
num++;
}
}
}
public static boolean isPalindrome(long num) {
String string = String.valueOf(num);
return string.equals(new StringBuilder(string).reverse().toString());
}
}
答案 2 :(得分:1)
您应该注意的第一件事是您的资源有限。即使您的实现是精确的并且所有递归调用都是正确的,您仍可能会收到错误。该错误表明您的JVM堆栈空间不足。尝试增加JVM堆栈的大小(有关详细信息,请参阅here)。
另一个重要的事情是寻找素数和回文数的分布。您的代码通过针对回文属性测试每个num+1
来运行。这是不正确的。当数字为素数时,您只测试回文 。这将使计算更容易(并减少递归调用)。我已相应地编辑了您的代码,并在543212(1003001)之后获得了最接近的回文数。这是:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
long num = input.nextLong();
//isPalindrome(num+1);
nextPrimePalindrome(num+1);
}
public static void nextPrimePalindrome(long num)
{
boolean flag=true;
while(flag)
{
if(isPrime(num))
if(isPalindrome(num))
{
System.out.println(num);
flag=false;
}
num++;
}
}
public static boolean isPrime(long num){
long i;
for(i=2;i<num;i++){
if(num%i == 0){
return false;
}
}
return true;
}
public static boolean isPalindrome(long num)
{
String word=Long.toString(num);
for(int i=0;i<word.length()/2;i++)
if(word.charAt(i)!=word.charAt(word.length()-i-1))
return false;
return true;
}
}