如何使BFS算法运行得更快?

问题描述

因此,我有一个函数可以查看网格(2D数组)并查找从起点到终点的所有路径。到目前为止,该算法可以按预期工作,并且可以获得所需的值。

问题在于它需要永远。它可以在100 x 100的网格上运行,但没有问题,但是一旦达到10000 x 10000的网格,大约需要10分钟才能给出答案,而我最多只需要1分钟。>

这是现在的样子:

public void BFS(Point s,Point e){
        /**
         * north,South,East,West coordinates
         */
        int[] x = {0,1,-1};
        int[] y = {1,-1,0};

        LinkedList<Point> queue = new LinkedList<>();
        queue.add(s);

        /**
         * 2D int[][] grid that stores the distances of each point on the grid
         * from the start
         */
        int[][] dist = new int[numRow][numCol];
        for(int[] a : dist){
            Arrays.fill(a,-1);
        }
        /**
        * "obstacles" is an array of Points that contain the (x,y) coordinates of obstacles on the grid
        * designated as a -2,which the BFS algorithm will avoid.
        */
        for(Point ob : obstacles){
            dist[ob.x][ob.y] = -2;
        }
        // Start point
        dist[s.x][s.y] = 0;

        /**
         * Loops over dist[][] from starting point,changing each [x][y] coordinate to the int
         * value that is the distance from S.
         */
        while(!queue.isEmpty()){                                        
            Point p = queue.removeFirst();
            for(int i = 0; i < 4; i++){                             
                int a = p.x + x[i];
                int b = p.y + y[i];
                if(a >= 0 && b >= 0 && a < numRow && b < numCol && dist[a][b] == -1){
                    dist[a][b] = 1 + dist[p.x][p.y];
                    Point tempPoint = new Point(a,b);
                    if(!queue.contains(tempPoint)){
                        queue.add(tempPoint);
                    }
                }
            }
        }

        /**
         * Works backwards to find all shortest path points between S and E,and adds each
         * point to an array called "validpaths"
         */
        queue.add(e);
        while(!queue.isEmpty()){
            Point p = queue.removeFirst();

            // Checks grid space (above,below,left,and right) from Point p
            for(int i = 0; i < 4; i++){
                int curX = p.x + x[i];
                int curY = p.y + y[i];

                // Index Out of Bounds check
                if(curX >= 0 && curY >= 0 && !(curX == start.x && curY == start.y) && curX < numRow && curY < numCol){
                    if(dist[curX][curY] < dist[p.x][p.y] && dist[curX][curY] != -2){ // -2 is an obstacle
                        Point tempPoint = new Point(curX,curY);
                        if(!validpaths.contains(tempPoint)){
                            validpaths.add(tempPoint);
                        }
                        if(!queue.contains(tempPoint)){
                            queue.add(tempPoint);
                        }
                    }
                }
            }
        }

因此,再次奏效,它确实很慢。我正在尝试获取一个O(n + m),但是我相信它可能正在O(n^2)中运行。

有人知道有什么好主意可以加快速度吗?

解决方法

观察到的低效率的明显原因是比较!validPaths.contains(tempPoint)!queue.contains(tempPoint)均为O(n)。要进行这些比较,您应该努力进行O(1)比较,这可以通过使用特殊的数据结构(例如hash-set或简单地使用bitset来完成)。

就目前而言,由于这些比较,您的实现显然是O(n ^ 2)。