Java:优化/提高DFS中的运行速度

Java:优化/提高DFS中的运行速度,java,arraylist,depth-first-search,Java,Arraylist,Depth First Search,所以我一直在研究一个问题,基本前提是给定一个任意大小的网格,我需要计算“旅行”的数量。巡更是从左上角点开始(我使用点x=1,y=1)并在左下角点结束(x=1 y=max,无论“y”的最大值是多少)的跑步。除此之外,它还必须一路接触其他点,并且只能访问网格中的任何点一次 按照我在下面写的方式,它运行时间约为42-45秒,但如果可能的话,我想让它在30秒或更短的时间内运行。所以,我的问题是,我能改变什么或者去掉什么,让它运行得更快 我尝试过使所有内容都不是静态的,并实例化该类(这给我的运行时间增加了

所以我一直在研究一个问题,基本前提是给定一个任意大小的网格,我需要计算“旅行”的数量。巡更是从左上角点开始(我使用点x=1,y=1)并在左下角点结束(x=1 y=max,无论“y”的最大值是多少)的跑步。除此之外,它还必须一路接触其他点,并且只能访问网格中的任何点一次

按照我在下面写的方式,它运行时间约为42-45秒,但如果可能的话,我想让它在30秒或更短的时间内运行。所以,我的问题是,我能改变什么或者去掉什么,让它运行得更快

我尝试过使所有内容都不是静态的,并实例化该类(这给我的运行时间增加了几秒钟)

导入java.awt.Point;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.Stack;
导入java.util.Date;
公共类编码难题
{
public static List lAllPoints=new ArrayList();
公共静态int iMaxX;
公共静态图像;
公共静态int-iCompletePaths=0;
公共静态void depthFirstSearch(当前点,堆栈结果)
{
if(结果包含(当前))
返回;
结果:推送(电流);
if(current.x==1&¤t.y==iMaxY&&result.size()==iMaxX*iMaxY)
{
//这是一条完整的道路
i完成路径++;
}
对于(点p:getPossibleMoves(当前))
{
深度优先搜索(p,结果);
}
//找不到路径
result.pop();
返回;
}
公共静态列表getPossibleMoves(点到点)
{
int iCurrentPointIndex=lAllPoints.indexOf(fromPoint);
List lPossibleMoves=new ArrayList();
if(fromPoint.x==1&&fromPoint.y==1)
{
//左上角点
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+iMaxY));
}
else if(fromPoint.x==1&&fromPoint.y==iMaxY)
{
//左下角点。应始终为最后一点。无有效移动。
//如果路径在结束之前到达此处,则不需要继续。
}
else if(fromPoint.x==iMaxX&&fromPoint.y==1)
{
//右上角
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-iMaxY));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+1));
}
else if(fromPoint.x==iMaxX&&fromPoint.y==iMaxY)
{
//右下角点
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-iMaxY));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-1));
}
else if(fromPoint.x==1&&fromPoint.y!=iMaxY)
{
//左侧的任何其他点
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+iMaxY));
}
else if(fromPoint.x==iMaxX)
{
//右侧的任何其他点
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-iMaxY));
}
else if(fromPoint.y==1)
{
//上面还有其他点吗
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-iMaxY));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+iMaxY));
}
else if(fromPoint.y==iMaxY&&fromPoint.x!=1)
{
//底部的任何其他点
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-iMaxY));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+iMaxY));
}
其他的
{
//不在边上的任何其他点。
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-1));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex-iMaxY));
lPossibleMoves.add(lAllPoints.get(iccurrentpointindex+iMaxY));
}
返回可能的移动;
}
公共静态无效设置网格(整数x,整数y)
{
iMaxX=x;
iMaxY=y;

对于(int i=1;i我要做的第一件事就是分析你的代码(正如Peter在对你的问题的评论中所说的)。如果不知道你在哪里花费时间,很难“加快速度”。但是你的算法可能有点效率低下。对于分析,你可以使用Oracle JVM附带的jvisualvm


您可能需要研究如何解决图形的问题,这正是您正在做的事情。有比暴力更有效的解决方案。

其他人怎么说。它将帮助您成为一名更好的程序员


除此之外,您正在寻找一个快速的赢家-从
堆栈切换到
,也就是说,这一变化使我的
Java7-server
机器的速度加快了44%。

我会减少代码为获得计数所做的工作量

public class CodingPuzzle2 {
    private final int width;
    private final int height;

    public CodingPuzzle2(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public int countPaths(int x, int y) {
        boolean[][] visited = new boolean[width][height];
        int[] count = {0};
        countPaths(x, y, visited, 1,  count);
        return count[0];
    }

    private void countPaths(int x, int y, boolean[][] visited, int depth, int[] count) {
        if (x < 0 || x >= width || y < 0 || y >= height || visited[x][y])
            return;
        visited[x][y] = true;
        try {
            if (x == 0 && y == height - 1) {
                if (depth == width * height)
                    count[0]++;
                return;
            }
            countPaths(x, y + 1, visited, depth+1, count);
            countPaths(x + 1, y, visited, depth+1, count);
            countPaths(x - 1, y, visited, depth+1, count);
            countPaths(x, y - 1, visited, depth+1, count);
        } finally {
            visited[x][y] = false;
        }
    }

    public static void main(String... args) {
        long start = System.nanoTime();
        CodingPuzzle2 cp = new CodingPuzzle2(10,4);
        int count = cp.countPaths(0, 0);
        long time = System.nanoTime() - start;
        System.out.printf("%,d paths found in %.3f seconds.%n", count, time / 1e9);
    }
}

除非您在问题中提到了一个特定的问题-它更适合您是否尝试过对代码进行性能分析?我还没有尝试过性能分析,您能推荐一些好的使用方法吗?(可能是免费的)另外,最简单、最快速的评测方法是使用开关运行JVM。然后是JDK中包含的。很简单,但这两个工具一开始就足够了。哇。这一个更改使我的完整运行时间缩短到25秒。我确实理解其他人试图告诉我的内容,我理解其重要性(我已经知道它在哪里花费了大部分时间。从我所看到的,我已经尽可能多地从中提取了。)无论如何,谢谢。Stack很旧(来自Java 1.0)而且已经被废弃很久了。它在那里只是为了保持兼容性,它基本上只是一个修改过的-这是一个同步
public class CodingPuzzle2 {
    private final int width;
    private final int height;

    public CodingPuzzle2(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public int countPaths(int x, int y) {
        boolean[][] visited = new boolean[width][height];
        int[] count = {0};
        countPaths(x, y, visited, 1,  count);
        return count[0];
    }

    private void countPaths(int x, int y, boolean[][] visited, int depth, int[] count) {
        if (x < 0 || x >= width || y < 0 || y >= height || visited[x][y])
            return;
        visited[x][y] = true;
        try {
            if (x == 0 && y == height - 1) {
                if (depth == width * height)
                    count[0]++;
                return;
            }
            countPaths(x, y + 1, visited, depth+1, count);
            countPaths(x + 1, y, visited, depth+1, count);
            countPaths(x - 1, y, visited, depth+1, count);
            countPaths(x, y - 1, visited, depth+1, count);
        } finally {
            visited[x][y] = false;
        }
    }

    public static void main(String... args) {
        long start = System.nanoTime();
        CodingPuzzle2 cp = new CodingPuzzle2(10,4);
        int count = cp.countPaths(0, 0);
        long time = System.nanoTime() - start;
        System.out.printf("%,d paths found in %.3f seconds.%n", count, time / 1e9);
    }
}
2,329 paths found in 1.758 seconds.