Java:堆空间错误,Euler项目14

时间:2016-01-31 10:24:24

标签: java arraylist error-handling heap-memory

我正在尝试解决project Euler problem number 14

  

为正整数集定义了以下迭代序列:

     
      
  • n→n / 2 n 是偶数)
  •   
  • n→3n + 1 n 是奇数)
  •   
     

使用上面的规则并从13开始,我们生成以下序列:

     

13→40→20→10→5→16→8→4→2→1

     

可以看出这个序列(从13开始到1完成)   包含10个术语。虽然尚未证实(Collat​​z问题),   据认为,所有起始数字都以1结束。

     

哪个起始编号低于一百万,产生最长的链?

     

注意:一旦链条启动,条款允许超过一百万。

这是我的方法:

public class Euler14 {

public static void main(String[] args) {
    int temp = 0;
    ArrayList<Integer> numbers = new ArrayList<>();
    ArrayList<Integer> numberOf = new ArrayList<>();

    for(int i = 2; i<1000000; i++) {

        numbers.add(i);
        temp = i;

        while(i!=1) {   

            if(i%2==0) {
                i = i/2;
            }

            else{
                i = (3*i)+1;
            }                    

            numbers.add(i);                
        }

            numberOf.add(numbers.size());
            Collections.sort(numberOf);

            if(numberOf.size()>1) {
                numberOf.remove(0);
            }
            numbers.clear();
            i = temp;

            System.out.println("Starting number " + i + "\n" + 
                               "Size: " + numberOf + "\n");  
    }     
}    
}

但是,在运行此程序时,我在i = 113282:

时收到此错误

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

我该怎么做才能解决此错误,如何改进我的代码?

4 个答案:

答案 0 :(得分:1)

您获得OutOfMemoryError的原因是序列中某些数字的大小太大而无法存储在32位Java整数中。因此会发生算术溢出并且while循环不会终止(直到列表变得太大并超出堆空间)。

如果使用long而不是整数,则代码应该运行完毕。

但是,您无需存储所有数字。所有你需要跟踪的是最好的起点和到目前为止看到的最长序列的长度。我倾向于提取一个方法/函数,它接受一个起始值并返回从那里开始的Collat​​z序列的长度。

答案 1 :(得分:0)

可以使用命令行选项增加JVM分配的堆大小:

-Xms<size>        initial Java heap size
-Xmx<size>        maximum Java heap size

请注意,这只会解决您的问题。例如,而不是113282,它可以达到1.000.000。

答案 2 :(得分:0)

你去,不是写得很优雅,但是有效。 :)

public static void main(String [] args){
    long temp = 1;
    int MAX = 13;
    int count = 0;
    long maxCount = 0;
    long maxNumber = 0;
    for(long i = 1000000;i >= 1; i--){
        count = 0;
        temp = i;
        while(temp != 1){
            count++; 
            if(temp % 2 == 0){
                temp = temp / 2;
            }else{
                temp = temp*3 +1;
            }
        }
        if(maxCount <= count){
            maxCount = count;
            maxNumber = i;
        }
        System.out.println("Number : "+i+" count : "+count);
    }
    System.out.println("Max Number : "+maxNumber +" Count : "+maxCount);
}

答案 3 :(得分:0)

您有一个好的方法,但是使用ArrayList可能会导致失败。而不是将每种可能的结果存储在列表中,请尝试在两种情况下都递增(currentCount ++)。完成循环后,执行此操作 if(currentCount> previousCount){ previousCount =当前 将测试编号设置回迭代器 数字= i}