【发布时间】:2012-03-05 08:49:32
【问题描述】:
有问题的问题可以在http://projecteuler.net/problem=14找到
我正在尝试我认为是一种新颖的解决方案。至少它不是蛮力。我的解决方案基于两个假设:
1) 遍历序列的次数越少,得到答案的速度就越快。 2) 一个序列必然比它的每个元素的序列长
所以我实现了一个包含所有可能出现在序列中的数字的数组。开始序列的最大数字是 999999(因为问题只要求您测试小于 1,000,000 的数字);因此,任何序列中可能的最大数字是 3 * 999999 + 1 = 2999998(这是偶数,因此将除以 2 以获得序列中的下一个数字)。所以数组只需要这个大小。 (在我的代码中,数组实际上是 2999999 个元素,因为我包含了 0 以便每个数字都匹配其数组索引。但是,这不是必需的,它是为了理解)。
所以一旦一个数字进入一个序列,它在数组中的值就变成 0。如果后续序列达到这个值,它们将知道不再继续,因为假设它们会更长。
但是,当我运行代码时,在引入“wh:
”的行出现以下错误Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3188644
由于某种原因,它正在尝试访问上述值的索引,该索引不应该是可访问的,因为它超过了可能的最大值 29999999。任何人都可以理解为什么会这样吗?
请注意,我不知道我的假设是否真的正确。我是业余程序员而不是数学家。我在做实验。希望一旦我得到正确的索引,我会发现它是否有效。
代码如下:
private static final int MAX_START = 999999;
private static final int MAX_POSSIBLE = 3 * MAX_START + 1;
public long calculate()
{
int[] numbers = new int[MAX_POSSIBLE + 1];
for(int index = 0; index <= MAX_POSSIBLE; index++)
{
numbers[index] = index;
}
int longestChainStart = 0;
for(int index = 1; index <= numbers.length; index++)
{
int currentValue = index;
if(numbers[currentValue] != 0)
{
longestChainStart = currentValue;
while(numbers[currentValue] != 0 && currentValue != 1)
{
numbers[currentValue] = 0;
if(currentValue % 2 == 0)
{
currentValue /= 2;
}
else
{
currentValue = 3 * currentValue + 1;
}
}
}
}
return longestChainStart;
}
【问题讨论】:
-
我怀疑如果您每次都打印出 currentValue 的值,这将是显而易见的(ish)。打印可能需要一些时间,但我认为您只是在当前值之上增长,因为您已经达到了一个高于最大值三分之一的奇数。
-
我不明白为什么你认为 2999998 是可能的最大数字...如果你从 999999 开始,你会得到:999999 -> 2999998 -> 1499999 -> 4499998,但是 4499998 > 2999998。 ..
-
我现在意识到了这一点。出于某种原因,我认为,因为任何奇怪的东西都会变成偶数,它会再次减少,一切都会好起来的。没想到增加的幅度远大于减少的幅度。感谢你们两位指出这一点。