我已经写了一些java代码来确定三个多维数据集给你一个给定数字的总和。 (对不起,我真的不确定如何解释它的作用,但代码很简单。)问题是,当搜索-100到100之间的数字时,代码运行得非常快。但是当搜索更大的区域时(数千或数万等)它开始运行非常慢,即使在寻找小数字时也是如此。我要问的是如何优化它,以及可能更方便地进行搜索的方法,从小整数开始并逐步向更大的整数进行搜索,而不是现在如何进行随机选择并检查它们答案。
以下是代码:
public class test{
public static void main(String[] args)
{
int want = -69;
double test;
boolean found = false;
int answer;
while(found == false)
{
int max = 100;
int min = max / 2;
int a = (int) (Math.random()*max - min);
int b = (int) (Math.random()*max - min);
int c = (int) (Math.random()*max - min);
test = Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3);
answer = (int) test;
if(answer == want) {
found = true;
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
}
}
}
}
答案 0 :(得分:1)
这通常不是一个容易的问题。更为系统化的方法是在a,b和c的给定值范围内测试a,b和c的每种可能组合。像这样:
public class Main{
static boolean foundSolution = false;
public static void main(String []args){
int limit = 10;
boolean[][][] alreadyChecked = new boolean[limit*2+1][limit*2+1][limit*2+1];
foundSolution = false;
printCubesOfNum(-69,limit,0,0,0,alreadyChecked);
}
public static void printCubesOfNum(int answer,int limit, int a, int b, int c,boolean[][][] alreadyChecked) {
if(!foundSolution && !alreadyChecked[a+limit][b+limit][c+limit] && a < limit && a > -limit && b < limit && b > -limit && c < limit && c > -limit) {
alreadyChecked[a+limit][b+limit][c+limit] = true;
int test = (int)Math.pow(a, 3) + (int)Math.pow(b, 3) + (int)Math.pow(c, 3);
if(test == answer) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
foundSolution = true;
}else{
printCubesOfNum(answer,limit,a+1,b,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b+1,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b,c+1,alreadyChecked);
printCubesOfNum(answer,limit,a-1,b,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b-1,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b,c-1,alreadyChecked);
}
}
}
}
请注意,此代码在找到 a 解决方案后停止。可以有多种解决方案,但也没有解决方案。
答案 1 :(得分:1)
我所要求的是[...]可能的方法,让它更系统地进行搜索,从小整数开始,逐步向更大的方向发展,[...]
而不是while
- 循环,您可以考虑使用嵌套的for
- 循环:
for (int a = min; a < max; ++a) {
for (int b = min; b < max; ++b) {
for (int c = min; c < max; ++c) {
int answer = (int) (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3));
if (answer == want) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
return;
}
}
}
}
但实际上你并不需要为 c 尝试每个可能的值;相反,你知道 c 3 = 想要 - a 3 - b'/ EM> 3 ;所以你可以直接计算它,看看它是否成功:
for (int a = min; a < max; ++a) {
for (int b = min; b < max; ++b) {
// Note: the '0.1' is to be robust if there's some roundoff error:
int c = (int) (0.1 + Math.pow(want - Math.pow(a, 3) - Math.pow(b, 3), 1.0/3.0));
int answer = (int) (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3));
if (answer == want && c >= min && c <= max) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
return;
}
}
}
就此而言,问题的对称性(加法的交换律)意味着我们只需要尝试 b 的值至少等于 a :
for (int b = a; b < max; ++b) {
另一个优化是避免Math.pow(..., 3)
,这通常比... * ... * ...
效率低得多(因为Math.pow
必须支持非整数指数,所以它的工作方式是采用对数和幂):
int c = (int) (0.1 + Math.pow(want - a * a * a - b * b * b, 1.0/3.0));
int answer = a * a * a + b * b * b + c * c * c;
另一个优化是限制 b 的范围,在内部for循环中,仅包含将 c 放在[范围内的值> min , max ):我们知道如果 b 太小,那么 c 就必须太大了,反之亦然:
int minB = (int) (0.1 + Math.pow(want - a * a * a - max * max * max, 1.0/3.0));
if (minB < a) {
minB = a;
}
int maxB = (int) (0.1 + Math.pow(want - a * a * a - min * min * min, 1.0/3.0)) + 1;
if (maxB > max) {
maxB = max;
}
for (int b = minB; b < maxB; ++b) {
当然,这些优化只能带你到目前为止。如果要搜索大范围的整数,则需要花费大量时间。但是,上述情况仍应比现在的情况有了很大改进。