Java 欧拉计划(第14页):递归问题
嗨,我在做欧拉计划中的科拉兹序列问题(问题14)。我的代码适用于100000以下的数字,但如果数字较大,则会出现堆栈溢出错误 有没有一种方法可以使用尾部递归重新分解代码,或者防止堆栈溢出。代码如下:Java 欧拉计划(第14页):递归问题,java,recursion,stack-overflow,collatz,Java,Recursion,Stack Overflow,Collatz,嗨,我在做欧拉计划中的科拉兹序列问题(问题14)。我的代码适用于100000以下的数字,但如果数字较大,则会出现堆栈溢出错误 有没有一种方法可以使用尾部递归重新分解代码,或者防止堆栈溢出。代码如下: import java.util.*; public class v4 { // use a HashMap to store computed number, and chain size static HashMap<Integer, Integer> hm =
import java.util.*;
public class v4
{
// use a HashMap to store computed number, and chain size
static HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
public static void main(String[] args)
{
hm.put(1, 1);
final int CEILING_MAX=Integer.parseInt(args[0]);
int len=1;
int max_count=1;
int max_seed=1;
for(int i=2; i<CEILING_MAX; i++)
{
len = seqCount(i);
if(len > max_count)
{
max_count = len;
max_seed = i;
}
}
System.out.println(max_seed+"\t"+max_count);
}
// find the size of the hailstone sequence for N
public static int seqCount(int n)
{
if(hm.get(n) != null)
{
return hm.get(n);
}
if(n ==1)
{
return 1;
}
else
{
int length = 1 + seqCount(nextSeq(n));
hm.put(n, length);
return length;
}
}
// Find the next element in the sequence
public static int nextSeq(int n)
{
if(n%2 == 0)
{
return n/2;
}
else
{
return n*3+1;
}
}
}
import java.util.*;
公共类v4
{
//使用HashMap存储计算的数字和链大小
静态HashMap hm=newhashmap();
公共静态void main(字符串[]args)
{
hm.put(1,1);
最终整数上限_MAX=Integer.parseInt(args[0]);
int len=1;
int max_count=1;
int max_seed=1;
对于(整数i=2;i最大计数)
{
最大计数=len;
max_seed=i;
}
}
System.out.println(最大种子数+“\t”+最大计数);
}
//求N的冰雹序列的大小
公共静态整数序列计数(整数n)
{
如果(hm.get(n)!=null)
{
返回hm.get(n);
}
如果(n==1)
{
返回1;
}
其他的
{
int length=1+seqCount(nextSeq(n));
hm.put(n,长度);
返回长度;
}
}
//查找序列中的下一个元素
公共静态int nextSeq(int n)
{
如果(n%2==0)
{
返回n/2;
}
其他的
{
返回n*3+1;
}
}
}
问题不在于堆栈的大小(您已经在记忆值),而在于
公共静态int seqCount(int n)
{
如果(hm.get(n)!=null){
返回hm.get(n);
}
if(n<1){
//这永远不会发生,对吗?;)
} ...
...
希望这就足够了:)
另外,在很多project euler问题中,您会遇到对BigNums的需求…旁注(因为似乎您实际上不需要对该问题进行尾部调用优化):尾调用优化在Java中不可用,据我所知,它甚至不受JVM字节码的支持。这意味着任何深度递归都是不可能的,您必须对其进行重构以使用其他循环构造。如果您正在计算Collatz序列的大小,最大值为1000000 您应该重新考虑使用整数类型。我建议使用大整数或可能的长
这应该可以缓解遇到的问题,但需要注意的是,根据JVM的不同,您可能仍然会耗尽堆空间。如果您将整数更改为长,将为您提供足够的空间来解决问题。 下面是我用来回答这个问题的代码:
for(int i=1;i<=1000000;i+=2)
{
steps=1;
int n=i;
long current=i;
while(current!=1)
{
if(current%2==0)
{
current=current/2;
}else{
current=(current*3)+1;
}
steps++;
}
if(steps>best)
{
best=steps;
answer=n;
}
}
for(inti=1;ibest)
{
最佳=步骤;
答案=n;
}
}
暴力强制,运行大约需要9秒我认为您需要以下两个提示:
import java.util.*;
import java .util.*;
public class file
{
public static void main(String [] args)
{
long largest=0;
long number=0;
for( long i=106239;i<1000000;i=i+2)
{
long k=1;
long z=i;
while(z!=1)
{
if(z%2==0)
{
k++;
z=z/2;
} else{
k++;
z=3*z+1;
}
}
if(k>largest)
{
number=i;
largest=k;
System.out.println(number+" "+largest);
}
}//for loop
}//main
}
公共类文件
{
公共静态void main(字符串[]args)
{
最大长=0;
长数=0;
用于(长i=106239;i最大)
{
数字=i;
最大=k;
System.out.println(数字+“”+最大值);
}
}//for循环
}//主要
}
您不仅可以使用递归,还可以使用单个循环来解决此问题。如果您写入int,则会出现溢出,因为它会在更改时生成很长时间,并且递归永远不会结束,因为从不等于1,您可能会得到堆栈溢出错误
以下是我的循环和递归解决方案:
public class Collatz {
public int getChainLength(long i) {
int count = 1;
while (i != 1) {
count++;
if (i % 2 == 0) {
i /= 2;
} else {
i = 3 * i + 1;
}
}
return count;
}
public static int getChainLength(long i, int count) {
if (i == 1) {
return count;
} else if (i % 2 == 0) {
return getChainLength(i / 2, count + 1);
} else {
return getChainLength(3 * i + 1, count + 1);
}
}
public int getLongestChain(int number) {
int longestChain[] = { 0, 0 };
for (int i = 1; i < number; i++) {
int chain = getChainLength(i);
if (longestChain[1] < chain) {
longestChain[0] = i;
longestChain[1] = chain;
}
}
return longestChain[0];
}
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(new Collatz().getLongestChain(1000000));
}
}
公共类Collatz{
公共整数getChainLength(长i){
整数计数=1;
而(i!=1){
计数++;
如果(i%2==0){
i/=2;
}否则{
i=3*i+1;
}
}
返回计数;
}
公共静态整型getChainLength(长i,整型计数){
如果(i==1){
返回计数;
}else如果(i%2==0){
返回getChainLength(i/2,计数+1);
}否则{
返回getChainLength(3*i+1,count+1);
}
}
公共整数getLongestChain(整数编号){
int longestChain[]={0,0};
对于(int i=1;i
在这里,您可以看看我对问题14的递归实现:
对于这个特殊的问题,可以使用long。(对于后面需要大于long的代码,我使用Python而不是Java,因为它会自动将整数提升为bignums)防止堆栈溢出?你怎么敢这么说!;)Scala(编译为JVM字节码的语言)支持有限的尾部递归,所以JVM可以做到这一点,但不是用Java或非常好:)请不要添加l
public class Collatz {
public int getChainLength(long i) {
int count = 1;
while (i != 1) {
count++;
if (i % 2 == 0) {
i /= 2;
} else {
i = 3 * i + 1;
}
}
return count;
}
public static int getChainLength(long i, int count) {
if (i == 1) {
return count;
} else if (i % 2 == 0) {
return getChainLength(i / 2, count + 1);
} else {
return getChainLength(3 * i + 1, count + 1);
}
}
public int getLongestChain(int number) {
int longestChain[] = { 0, 0 };
for (int i = 1; i < number; i++) {
int chain = getChainLength(i);
if (longestChain[1] < chain) {
longestChain[0] = i;
longestChain[1] = chain;
}
}
return longestChain[0];
}
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(new Collatz().getLongestChain(1000000));
}
}