如何优化/更改“搜索”程序Java

时间:2017-01-22 15:15:30

标签: java optimization random

我已经写了一些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);
            }
        }
    }
}

2 个答案:

答案 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 解决方案后停止。可以有多种解决方案,但也没有解决方案。

您可以查看similar question on mathoverflow here

答案 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) {

当然,这些优化只能带你到目前为止。如果要搜索大范围的整数,则需要花费大量时间。但是,上述情况仍应比现在的情况有了很大改进。