我的实验室问题之一是写一段代码来计算Recamán序列的第n个值。
我给出的测试用例上升到Recamán序列的第100,000个值,确定该值本身的算法不是我的问题,我的问题是以一种不需要太多方式编写程序的问题长期运行。为了实现这一点,我的教授给了我们提示,建议使用大小为n * 10的足够大的Boolean [],并使用它来跟踪哪些整数值已属于所生成序列的一部分,而不是遍历整个先前生成的值
我有一些代码,我相信应该可以很好地解决这个问题,但是我遇到的问题是数组索引不足。通过我们提供的自动测试仪,它会随机询问1-100,000的第n个值。但是,在我的Boolean []中,我遇到了空间不足的问题,以检查数字是否已生成。
我的代码如下
public static int recaman(int n){
int[] seq = new int[n];
boolean[] check = new boolean[10 * n];
seq[0]=0;
check[0]=true;
for(int k=1;k<=n;k++){
int minusVal = seq[k-1]-k;
int plusVal = seq[k-1] + k;
if((minusVal>0)&&(!check[seq[minusVal]])){
seq[k]= minusVal;
check[minusVal] = true;
}else{
seq[k] = plusVal;
check[plusVal]=true;
}
}
return seq[n];
}
并运行recaman(100)会导致以下错误
Java.lang.ArrayIndexOutOfBoundsException:104
在 P2J2.recaman(P2J2.java:78)
奇怪的是,对于小数字来说,错误并非每次都会出现,而对于〜400以上的任何数字,几乎都会一直发生。
我似乎无法弄清楚我在做错什么,如果有人可以指出正确的方向,我将非常感激。
答案 0 :(得分:2)
!check [minusVal]是正确的方法。
public static int recaman(int n)
{
int[] seq = new int[n];
boolean[] check = new boolean[10 * n];
seq[0] = 0;
check[0] = true;
for (int k = 1; k < n; k++)
{
int minusVal = seq[k - 1] - k;
int plusVal = seq[k - 1] + k;
if ((minusVal > 0) && (!check[minusVal]))
{
seq[k] = minusVal;
check[minusVal] = true;
} else
{
seq[k] = plusVal;
check[plusVal] = true;
}
}
return seq[n - 1];
}
答案 1 :(得分:1)
对于k=16
minusVal = 104
,您检查!check[seq[minusVal]]
。这就是错误的原因。似乎您也需要制作int[] seq = new int[n * 10];
。希望能帮助到你!
PS。我用int[] seq = new int[n * 10];
测试了它,但仍然有同样的错误。通常,条件!check[seq[minusVal]]
是错误的,并且可能导致错误的结果。您应将其替换为!check[minusVal]
,因为您想检查以前是否存在MinusVal
,而不是seq[minusVal]
。
这段代码对我来说没有错误:
public class HelloWorld {
public static int recaman(int n){
int[] seq = new int[n * 10];
boolean[] check = new boolean[10 * n];
seq[0]=0;
check[0]=true;
for(int k=1;k<=n;k++){
int minusVal = seq[k-1]-k;
int plusVal = seq[k-1] + k;
if((minusVal>0)&&(!check[minusVal])){
seq[k]= minusVal;
check[minusVal] = true;
}else{
seq[k] = plusVal;
check[plusVal]=true;
}
}
return seq[n];
}
public static void main(String[] args) {
System.out.println("Hello World!");
recaman(100000);
}
}