Java DFS方法未生成预期输出
因此,我们的目标是使用dfs打印所有可能的数字,这些数字可以由电路板上的一系列相邻字符组成。我所说的相邻是指在垂直、水平或对角方向上彼此相邻。总共有8个运动方向。例句:下面的黑板Java DFS方法未生成预期输出,java,algorithm,depth-first-search,Java,Algorithm,Depth First Search,因此,我们的目标是使用dfs打印所有可能的数字,这些数字可以由电路板上的一系列相邻字符组成。我所说的相邻是指在垂直、水平或对角方向上彼此相邻。总共有8个运动方向。例句:下面的黑板 1 2 3 4 为了更简单,让我们假设我们总是从第0行第0列开始,也就是1。所以可能的数字是:1,12,13,14,123,124,132,134,142,143,1234等等(这个例子很简单,因为所有的数字都是直接相邻的) 因此,我有以下代码: static char[][] grid; static int ro
1 2
3 4
为了更简单,让我们假设我们总是从第0行第0列开始,也就是1。所以可能的数字是:1,12,13,14,123,124,132,134,142,143,1234等等(这个例子很简单,因为所有的数字都是直接相邻的)
因此,我有以下代码:
static char[][] grid;
static int rows;
static int columns;
public static void main(String[] args) {
//test grid. made it small so that solutions are easy to count
grid = new char[][]{
new char[]{'1', '2'},
new char[]{'3', '4'},
};
rows = grid.length;
columns = grid[0].length;
dfs(0, 0, new boolean[rows][columns], new StringBuilder());
}
public static void dfs(int row, int col, boolean[][] visited, StringBuilder builder){
visited[row][col] = true;
builder.append(grid[row][col]);
System.out.println(builder.toString());
//the 2 loops are for the 8 movement directions
for(int x = -1; x <= 1; x++){
for(int y = -1; y <= 1; y++){
//index bounds check
if((row + x >= 0) && (row + x < rows) && (col + y >= 0) && (col + y < columns)){
if(!visited[row + x][col + y]){
dfs(row + x, col + y, visited, builder);
// I tried changing it so that it passes a COPY of 'visited' and 'builder',
// but output still the same
dfs(row + x, col + y, Arrays.copyOf(visited, visited.length), new StringBuilder(builder));
}
}
}
}
}
这些数字是解决方案的一部分,但远不止这些。该错误可能与将同一对象传递到递归dfs()调用有关,但我尝试对其进行更改,使其仅复制该对象,并且仍然提供相同的输出。
有什么想法吗?您应该能够在不创建访问矩阵副本的情况下实现预期输出 重要的一点是,在每次沿着路径完成访问后,将
已访问的[row][col]
设置为false
例如:
假设您已经遍历了'12',现在还有'3'和'4'要访问。在当前状态下,“1”和“2”的矩阵值设置为true,“3”和“4”的矩阵值设置为false。生成完以“12”开头的所有字符串后,将开始查看以“13”开头的所有字符串
但看看这里发生了什么!您已将已访问的值“2”设置为true,因此将来不会生成包含“2”的字符串
这就是为什么在从该点开始生成所有路径后,必须将访问的[row][col]
设置为false
要真正理解这一点,请用笔和纸跟踪代码,这样您会更好地记住它
注:
实际上,在上面描述的示例中,您永远不会生成以“13”开头的字符串,因为访问[1][1]
之前会被设置为true,因此不会再次访问3。我忽略了那个事实来说明一点
为什么我建议不要对每个递归调用进行深度复制?简单,节省时间和空间。每个调用将占用O(m*n)空间和时间来生成和存储新的访问矩阵
以下是正确代码的一个变体:
import java.util.*;
public class DFS{
static char[][] grid;
static int rows;
static int columns;
public static void main(String[] args) {
//test grid. made it small so that solutions are easy to count
grid = new char[][]{
new char[]{'1', '2'},
new char[]{'3','4'},
};
rows = grid.length;
columns = grid[0].length;
ArrayList<String>list = new ArrayList<>();
dfs(0, 0, new boolean[rows][columns], new StringBuilder());
//System.out.println(list);
}
public static void dfs(int row, int col, boolean[][] visited, StringBuilder builder){
visited[row][col] = true;
builder.append(grid[row][col]);
System.out.println(builder);
for(int x = -1; x <= 1; x++){
for(int y = -1; y <= 1; y++){
//index bounds check
if((row + x >= 0) && (row + x < rows) && (col + y >= 0) && (col + y < columns)){
if(!visited[row + x][col + y]){
dfs(row + x, col + y, visited, builder);
}
}
}
}
visited[row][col]=false;
builder.deleteCharAt(builder.length()-1);
}
}
import java.util.*;
公共类DFS{
静态字符[][]网格;
静态int行;
静态int列;
公共静态void main(字符串[]args){
//测试网格。使其变小,以便于计算解决方案
网格=新字符[][]{
新字符[]{'1','2'},
新字符[]{'3','4'},
};
行=网格长度;
columns=网格[0]。长度;
ArrayList=新的ArrayList();
dfs(0,0,新的布尔值[行][列],新的StringBuilder());
//系统输出打印项次(列表);
}
公共静态void dfs(int行、int列、布尔值[][]已访问、StringBuilder){
访问[行][列]=真;
builder.append(网格[行][列]);
System.out.println(生成器);
对于(int x=-1;x=0)和&(col+y
编辑:我忘记突出显示添加的最后一行代码,在那里我删除了当前
StringBuilder
的最后一个字符。这是回溯位,因此在生成所有“12xx”字符串后,您可以删除“2”,将其替换为“3”,现在开始探索“13xx”字符串系列。我不确定Arrays.copyOf()
在二维数组上的行为,但它几乎肯定不会像您认为的那样。请看。幸运的是,以前有人问过一个问题,所以我不需要研究^^@JanezKuhar这很有趣。。。制作了一个手动二维阵列副本,现在可以使用了。Thx:)
import java.util.*;
public class DFS{
static char[][] grid;
static int rows;
static int columns;
public static void main(String[] args) {
//test grid. made it small so that solutions are easy to count
grid = new char[][]{
new char[]{'1', '2'},
new char[]{'3','4'},
};
rows = grid.length;
columns = grid[0].length;
ArrayList<String>list = new ArrayList<>();
dfs(0, 0, new boolean[rows][columns], new StringBuilder());
//System.out.println(list);
}
public static void dfs(int row, int col, boolean[][] visited, StringBuilder builder){
visited[row][col] = true;
builder.append(grid[row][col]);
System.out.println(builder);
for(int x = -1; x <= 1; x++){
for(int y = -1; y <= 1; y++){
//index bounds check
if((row + x >= 0) && (row + x < rows) && (col + y >= 0) && (col + y < columns)){
if(!visited[row + x][col + y]){
dfs(row + x, col + y, visited, builder);
}
}
}
}
visited[row][col]=false;
builder.deleteCharAt(builder.length()-1);
}
}