HackerEarth出现内存错误问题:反向素数

时间:2015-06-01 12:23:35

标签: java optimization out-of-memory primes

  

生成尽可能多的不同质数 P ,使反向(P)为   也是素数,不等于 P

     

输出:每行打印一个整数(≤10^ 15)。不要打印超过   总共10 ^ 6个整数。

     

评分:让 N =正确输出。    M =输出不正确。您的分数将最大(0,N-M)。

     

注意:P和反向(P)中只有一个将被计为正确。如果两者都在文件中,则会将其视为不正确。

     

样本输出 107 13 31 17 2

     

解释

     

得分为1.由于13,107,17是正确的。 31是不正确的,因为   13已经存在了。 2是不正确的。

这是我编写的代码,它在Eclipse中给出了输出Out Of Memory错误。

由于内存要求是256 MB,我设置-Xmx256M,但由于它给我一个Out Of Memory错误,我一定误解了这个问题,或者我的代码在内存利用率方面有问题。我在这做错了什么?我为lONGMAX10000等较小的1000000获得了所需的输出。

public class ReversePrime {
    final static long lONGMAX=1000000000000000L;
    final static int MAXLISTSIZE=1000000;
    final static boolean[] isPrime=isPrime();
    public static void main(String...strings ){

        Set<Long> reversedCheckedPrime = new LinkedHashSet<Long>();
        int isPrimeLength=isPrime.length;
        for(int i = 0; i < isPrimeLength ; i++){
            if( isPrime[i]){
                long prime = 2 * i + 3;
                long revrse= reversePrime(prime);
                if ( (!(prime==revrse)) && (!reversedCheckedPrime.contains(revrse)) && 
                        (reversedCheckedPrime.size()<=MAXLISTSIZE)){
                    reversedCheckedPrime.add(prime);
                }
                if (reversedCheckedPrime.size()==MAXLISTSIZE){
                    break;
                }
            }
        }   

        for (Long prime : reversedCheckedPrime){
            System.out.println(prime);
        }

    }
    private static long reversePrime(long prime) {
        long result=0;
        long rem;
        while(prime!=0){
            rem = prime % 10;
            prime = prime / 10;
            result = result * 10 + rem ;
        }
        return result;
    }
    private static boolean[] isPrime() {
        int root=(int) Math.sqrt(lONGMAX)+1;
        root = root/2-1;
        int limit= (int) ((lONGMAX-1)/2);
        boolean[] isPrime=new boolean[limit];
        Arrays.fill(isPrime, true);
        for(int i = 0 ; i < root ; i++){
            if(isPrime[i]){
                for( int j = 2 * i * (i + 3 ) + 3, p = 2 * i + 3; j < limit ; j = j + p){
                    isPrime[j] = false;
                }
            }

        }
        return isPrime;
    }
}

Hackerearth Link

3 个答案:

答案 0 :(得分:2)

有两种可能性:

  • 您使用-Xmx256M表示256 MB堆。但是,除了堆之外,你的VM可能会在尝试获取更多内容时被杀死。

  • 您为VM提供256 MB但您的程序需要更多并被杀死。 <----正如RealSkeptic所说,情况确实如此。

要获得1M素数,您需要调查一些&lt; 100M数字(*)。因此,如果主筛工作在100_000_000以下,它应该可以工作。这样筛子也可以反转。通过跳过平均值,您只需要50 MB,因此您可以将限制设置为100M。

您可以使用位而不是字节来减少因子8使用的内存。通过忽略以偶数开头的数字,你可以将它减少2倍,但这很复杂。

(*)这是您在提交之前可以轻松尝试的内容。

答案 1 :(得分:2)

你宣布:

final static long lONGMAX=1000000000000000L;

然后在分配布尔数组时,计算:

int limit= (int) ((lONGMAX-1)/2);

根据该定义,limit将为1,382,236,159。这是1.3Gb,假设布尔值占用一个字节。您可能认为VM每个布尔值只分配一个位,但这不是它的工作原理。

请考虑使用java.util.BitSet

答案 2 :(得分:0)

你实际上应该用List替换你的boolean [],因为内存可能来自这个表。您没有使用最佳策略,因为您将每个长期存在的所有价值都堆叠起来。 你最好只在内存中保留素数,尝试重新考虑素数的定义,并继续进行迭代演绎。