我正在尝试将递归算法转换为迭代算法,以提高性能,因为我的程序正试图从具有迷宫的文本文件中获取所有路径。我知道DP比迭代要快,但是我很想看到递归,迭代和DP在解决此问题时的区别。
我想知道是否有一种方法可以在不使用 stack 的情况下将算法转换为迭代式。
这是我到目前为止递归所做的事情。
int[][] maze = new int[Integer.valueOf(dimensions[1])]
[Integer.valueOf(dimensions[0])];
int colA = maze[0].length;
int colB = colA;
int rowA = 0;
int rowB = 0;
for (int i = 0; i < maze.length; i++) {
String currLine = lines.get(i+1);
int j = 0;
for (char c : currLine.toCharArray()) {
maze[i][j] = c == '*' ? -1 : 0;
if (c == 'A') {
maze[i][j] = 1;
rowA = i;
colA = j;
} else if (c == 'B') {
maze[i][j] = 2;
rowB = i;
colB = j;
}
j++;
}
}
return getAllPaths(maze, rowA, colA);
}
private static int getAllPaths(int[][] maze, int i, int j) throws IOException {
if(maze[i][j] == -1) {
return 0;
}
if(maze[i][j] == 2) {
return 1;
}
return getAllPaths(maze, i+1, j) + getAllPaths(maze, i, j+1);
}
任何从此处开始将其转换为迭代的提示或建议,将不胜感激!
答案 0 :(得分:1)
迭代与递归不会产生明显的性能差异。
您需要做的是编写代码memoize,这样您就不必多次进行相同的计算。
为了说明这一点:在3x5矩阵中,您将像这样行走:
X → X → X → X → X
↓ ↓ ↓ ↓ ↓
X → X → X → X → X
↓ ↓ ↓ ↓ ↓
X → X → X → X → X
将对该坐标调用X
的次数替换为getAllPaths
的次数,您将得到:
1 → 1 → 1 → 1 → 1
↓ ↓ ↓ ↓ ↓
1 → 2 → 3 → 4 → 5
↓ ↓ ↓ ↓ ↓
1 → 3 → 6 → 10 → 15
如您所见,在没有备注的情况下,坐标4,2被调用了15次。这对性能非常不利。如果将结果保存到其中,只进行一次递归调用,您将获得更好的性能。
我将把它留给您作为练习,以了解有关记忆的更多信息,以便您可以将其应用于代码。
更新
引用维基百科:
记忆化是一种优化技术,主要用于通过存储昂贵的函数调用的结果并在再次出现相同的输入时返回缓存的结果来加快计算机程序的速度。
因此,您需要缓存调用方法的结果,这意味着您需要与迷宫大小相同的缓存。
private static int getAllPaths(int[][] maze, int row, int col) {
int[][] cache = new int[maze.length][maze[0].length];
for (int i = 0; i < cache.length; i++) {
Arrays.fill(cache[i], -1);
}
return getAllPaths(maze, cache, row, col);
}
private static int getAllPaths(int[][] maze, int[][] cache, int row, int col) {
// Check cache
if (cache[row][col] != -1)
return cache[row][col];
// Normal logic
int paths;
if (maze[row][col] == -1) {
paths = 0;
} else if (maze[row][col] == 2) {
paths = 1;
} else {
paths = getAllPaths(maze, cache, row+1, col) + getAllPaths(maze, cache, row, col+1);
}
// Save result in cache
cache[row][col] = paths;
return paths;
}