Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何优化使用嵌套for循环的代码?_Java_Performance_Optimization_Time Complexity_Nested Loops - Fatal编程技术网

Java 如何优化使用嵌套for循环的代码?

Java 如何优化使用嵌套for循环的代码?,java,performance,optimization,time-complexity,nested-loops,Java,Performance,Optimization,Time Complexity,Nested Loops,我正在解决一个问题,我需要确定一个点是否位于连接其他两个点的线上。例如,如果我有点a、b、c,我想确定c是否在连接a和b的线段上。在我的代码中,我有一个点,示例中的me a和两个点列表,示例中的hits b和示例中的reachable c。对于点击中的每个点,我想确定在连接我和点击中的点的线段上是否有任何可到达的点。如果该线段上有一个点,则需要减小numHits。这是我的密码: Point me; //Point a from the example above ArrayList<Poi

我正在解决一个问题,我需要确定一个点是否位于连接其他两个点的线上。例如,如果我有点a、b、c,我想确定c是否在连接a和b的线段上。在我的代码中,我有一个点,示例中的me a和两个点列表,示例中的hits b和示例中的reachable c。对于点击中的每个点,我想确定在连接我和点击中的点的线段上是否有任何可到达的点。如果该线段上有一个点,则需要减小numHits。这是我的密码:

Point me; //Point a from the example above
ArrayList<Point> hits = new ArrayList<>();  //a list of Point b's from the example above
ArrayList<Point> reachable = new ArrayList<>();  //a list of point c's from the example above

for(Point hit : hits) {
    for(Point p : reachable) {
        if(!hit.equals(p) && !me.equals(p)) {
            //find the equation of a line from me to hit
            if(hit.x - me.x == 0) { //if the line has an undefined slope... if the line is vertical
                if( (((p.y <= hit.y) && (p.y >= me.y)) || ((p.y >= hit.y) && (p.y <= me.y))) && p.x - me.x == 0) {  //if there is any occupied point on that line in between me and the hit, that point blocks the hit
                    numHits--;
                    break;
                }
            } else {
                //create a line from me to the hit... if there is any occupied point on that line in between me and the hit, that point blocks the hit
                double deltaY = hit.y - me.y;
                double deltaX = hit.x - me.x;

                double m = deltaY / deltaX; //slope
                double b = me.y - (double)(m*me.x);  //y intercept

                if((double) p.y == ((double)(m * p.x) + b)) {  //if this point is on the same line 
                    if( ((p.x <= hit.x && p.x >= me.x) && (p.y <= hit.y && p.y >= me.y)) ||
                                ((p.x <= hit.x && p.x >= me.x) && (p.y >= hit.y && p.y <= me.y)) || 
                                ((p.x >= hit.x && p.x <= me.x) && (p.y >= hit.y && p.y <= me.y)) ||
                                ((p.x >= hit.x && p.x <= me.x) && (p.y <= hit.y && p.y >= me.y))) {  //if the point is in between me and the hit
                        numHits--;
                        break;
                    }
                }
            }
        }
    }
}
我的代码用来确定我和点击中的每个点之间是否有任何可到达的点,当点击量越大,可到达的点越多,速度就越慢。例如,如果hits的大小为780000,reachable的大小为1500000,则代码需要很长时间才能运行。我想知道我如何才能优化它以更快地运行。我不确定瓶颈问题是在循环本身还是在循环中的代码中。非常感谢任何帮助或优化想法。谢谢大家!

我建议你看看。它有很多方法,包括确定一个点甚至一条线是否在给定的线段上的方法


我还建议您使用地图来记忆您可能已经遇到的现有点和其他信息。这样你就不会重复计算了。由于浮点运算可能会产生微小的差异,因此您可能必须使用一些可接受的错误来确定结果的有效性。

优化代码的一种方法是将点me移动到原点,然后将所有点划分到相应的象限,现在你只需要比较相同象限中的点

我将在下面写一个粗略的算法

1. Shift the point me to origin

2. Shift all other points, ie hits and reachable to origin ( this can be done by  subtracting X and Y of point me from all other X and Y ) 

3. Now divide hits and reachable to 4 quadrants based on their X and Y components, now you will have 4 arrays for hits and 4 arrays for reachable


4. You can also reduce the number of points in reachable by comparing them against the greatest point in hits like below, do this for all quadrants


    a. find greatest |X| (mode(X)) and greatest |Y| of hits in each quadrant, lets call it me.|x| and me.|y|

     b. for(Point p : reachable) {
              if(p.|x| > me.|x| or p.|y| > me.|y|) then remove p from reachable }
    since these points will be outside of the  line segment formed by me and hits

5. Now you can compare the values, using nested for loops as you did, you will have to use different conditions for each quadrant
不要忘记添加边缘条件并从原点向后移动

将每条线ac投影到x=0或y=0,以较小的值为准,以最小化舍入误差。对这些截取进行排序或散列,保留对每个c的引用,确保保留重复项

然后,对于每一行ab,也将其投影到x=0或y=0,以较小的值为准,并在排序或散列的集合中搜索匹配的截距。这将为您提供少量候选线段,这些线段通过a、b和c位于同一条线上;您只需检查该点是否位于端点a.xc.x>b.x内,然后再次检查y


小心舍入误差。

输入780000次点击和1500000次可到达,这是1万亿次潜在迭代。我可以想象这需要很长时间。你需要一次处理那么多数据吗?您有没有办法重新设计您的系统,以要求/处理更少的输入?也许你可以合并/展平输入中一些更一致的部分,如线性运动序列?@VinceEmigh在大多数情况下,处理的数据量将远小于780000和1500000。然而,在极少数情况下,代码仍然需要能够处理像这样大的数字。介于两者之间是什么意思?。如果一个点是原点,另一个是10,10,那么5,5在两者之间,3,7也在两者之间,或者你的意思是在由点a和点b构成的同一线段上?@WJS我想说的是,一个点是否在原点和另一个点之间的直线上。如果原点是0,0,另一个点是10,10,那么5,5在中间,3,7不在中间,11,11不在中间。我会更新这个问题,让它更清楚。那么你是说在线上,我该怎么做呢?我有点搞不懂你把一条线投影到x=0或y=0是什么意思