Java:堆空间错误,Euler项目14
我试图解决: 为正整数集定义以下迭代序列:Java:堆空间错误,Euler项目14,java,arraylist,error-handling,heap-memory,Java,Arraylist,Error Handling,Heap Memory,我试图解决: 为正整数集定义以下迭代序列: n→ n/2(n为偶数) n→ 3n+1(n为奇数) 使用上述规则并从13开始,我们生成以下序列: 十三,→ 40→ 20→ 10→ 5.→ 16→ 8.→ 4.→ 2.→ 一, 可以看出,该顺序(从13开始,到1结束) 包含10个术语。虽然还没有被证明(科拉兹问题), 人们认为所有的起始数字都以1结束 哪一个起始数字,在一百万以下,产生的链条最长 注:一旦链开始,条款允许超过一百万 这是我的方法: public class Euler14 {
- n→ n/2(n为偶数)
- n→ 3n+1(n为奇数)
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");
}
}
}
公共类Euler14{
公共静态void main(字符串[]args){
内部温度=0;
ArrayList编号=新的ArrayList();
ArrayList numberOf=新的ArrayList();
对于(int i=2;i1){
移除次数(0);
}
数字。清除();
i=温度;
System.out.println(“起始编号”+i+“\n”+
“大小:”+numberOf+“\n”);
}
}
}
但是,当运行此程序时,我在I
=113282处得到此错误:
线程“main”java.lang.OutOfMemoryError中出现异常:java堆空间
如何解决此错误,以及如何改进代码?可以使用命令行选项增加JVM分配的堆大小:
-Xms<size> initial Java heap size
-Xmx<size> maximum Java heap size
-Xms初始Java堆大小
-Xmx最大Java堆大小
考虑到这只会解决你的问题。因此,与113282相比,它可能会达到1.000.000,例如。导致OutOfMemoryError的原因是序列中某些数字的大小太大,无法存储在32位Java整数中。因此会发生算术溢出,while循环不会终止(直到列表变得太大并超过堆空间) 如果使用long而不是整数,代码应该一直运行到完成
但是,您不需要存储所有的数字。所有你需要跟踪的是最好的起点和到目前为止看到的最长序列的长度。我倾向于提取一个方法/函数,该方法/函数接受一个起始值并返回从那里开始的Collatz序列的长度。好了,写得不优雅,但很有效。:)
publicstaticvoidmain(字符串[]args){
长期温度=1;
int MAX=13;
整数计数=0;
长最大计数=0;
长maxNumber=0;
对于(长i=1000000;i>=1;i--){
计数=0;
温度=i;
while(温度!=1){
计数++;
如果(临时%2==0){
温度=温度/2;
}否则{
温度=温度*3+1;
}
}
如果(maxCount您有一个很好的方法,但是使用ArrayList可能会导致失败。不要在列表中存储每个可能的结果,而是尝试在这两种情况下递增(currentCount++)。完成循环后,执行此操作
如果(currentCount>previousCount){
前一计数=当前计数
将测试编号设置回迭代器
数字=i}最直接的问题是,您再次修改循环中的i
变量。因此,您当前没有传递2到1000000之间的所有值。另一个提示:如果您已经知道,从13开始的collatz序列的长度为10,您能用这个事实计算26的长度吗?我明白您的意思。您知道吗这意味着没有必要检查小于500000的数字?因为2的乘法会导致长度增加1=>没有小于500000的数字会产生比大于500000的更长的collatz序列?不。但是可以使用查找,将结果保存到计算中。所以当u为每个新数字计算一个序列,如果该数字已经存在,请查看该查找。如果是,则可以停止并使用该现有结果。此外,还可以将在该序列中遇到的所有数字及其各自的结果相加。
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);
}