Java 高效搜索多个项目的二维矩阵
我有一个25x25的网格,看起来像这样。在整个网格中有两个随机的字符串序列,我正在尝试开发一些有效的方法来搜索网格并找到每个位置的点 我看了两个在2D数组中搜索的算法示例,大多数算法都集中在查找单个字符或数字上 在这个特定的实例中,我有什么样的搜索选项?我在一次搜索中实现了一个基本步骤,如下所示:Java 高效搜索多个项目的二维矩阵,java,algorithm,search,Java,Algorithm,Search,我有一个25x25的网格,看起来像这样。在整个网格中有两个随机的字符串序列,我正在尝试开发一些有效的方法来搜索网格并找到每个位置的点 我看了两个在2D数组中搜索的算法示例,大多数算法都集中在查找单个字符或数字上 在这个特定的实例中,我有什么样的搜索选项?我在一次搜索中实现了一个基本步骤,如下所示: public void search(String[][] grid) { int cellsSearched = 0; List<Point> cLocations =
public void search(String[][] grid) {
int cellsSearched = 0;
List<Point> cLocations = new ArrayList<>();
List<Point> sLocations = new ArrayList<>();
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
if (cLocations.size() == 5 && sLocations.size() == 3) break;
if (grid[i][j].equals("S")) {
sLocations.add(new Point(i, j));
} else if (grid[i][j].equals("C")) {
cLocations.add(new Point(i, j));
}
cellsSearched++;
}
}
}
公共作废搜索(字符串[]网格){
int cellsSearched=0;
List cLocations=new ArrayList();
列表位置=新的ArrayList();
对于(int i=0;i
但这显然不是最有效的搜索方式
我曾想过将网格分割成象限,然后一次搜索一个象限,但这似乎仍然有太多潜在的缺陷。(例如,两个序列都位于搜索的最后一个象限中)
我的问题是,如何以尽可能少的步骤搜索此网格并收集其序列中每个字符的坐标?有一个技巧可用于改进搜索的运行时间
但是因为它是一个网格,而且因为我们没有关于
'S'
和'C'
的位置的任何信息,所以时间复杂性将保持O(n^2)
这样一来,
一旦你点击了
'S'
或'C'
,你实际上可以从那里存储它们的整个序列。基本上,您必须检查当前字符两侧是否有相同的字符,然后继续您可以有一个额外的
2D
布尔值数组,用于跟踪ArrayList
中包含哪些点以下是获得更好想法的代码:
public void search(String[][] grid) {
int cellsSearched = 0;
List<Point> cLocations = new ArrayList<>();
List<Point> sLocations = new ArrayList<>();
boolean[][] map = new boolean[grid.length][grid[0].length];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
if (cLocations.size() == 5 && sLocations.size() == 3) break;
if(!map[i][j]) {
if (grid[i][j].equals("S")) {
getSeries(i, j, "S", grid, map, sLocations);
} else if (grid[i][j].equals("C")) {
getSeries(i, j, "C", grid, map, sLocations);
}
}
cellsSearched++;
}
}
}
public boolean inbounds(int i, int j, String[][] grid) {
return ( 0 <= i && i < grid.length ) && ( 0 <= j && j < grid[i].length );
}
public void getSeries(int i, int j, String toFind,String[][] grid, boolean map[][], ArrayList<Point> locations) {
/**
* This function basically checks if 'i' and 'j' are safe so that accessing grid[i][j]
* would not cause ArrayOutOfBoundsException
*/
if(!inbounds(i, j, grid)) {
return;
}
String matched = grid[i][j];
if(!map[i][j] && matched.equals(toFind)) {
map[i][j] = true;
locations.add(new Point(i, j));
// Going up
getSeries(i - 1, j, toFind, grid, map, locations);
// Going down
getSeries(i + 1, j, toFind, grid, map, locations);
// Going left
getSeries(i, j - 1, toFind, grid, map, locations);
// Going right
getSeries(i, j + 1, toFind, grid, map, locations);
/*
(i+1, j-1) -> Going Bottom Left
(i+1, j+1) -> Going Bottom Right
(i-1, j-1) -> Going Top Left
(i-1, j+1) -> Going Top Right
*/
}
}
公共作废搜索(字符串[]网格){
int cellsSearched=0;
List cLocations=new ArrayList();
列表位置=新的ArrayList();
布尔[][]映射=新布尔[grid.length][grid[0.length];
对于(int i=0;i左上角
(i-1,j+1)->右上角
*/
}
}
您可以看到,一旦点击'S'
或'C'
,getSeries
函数将自动将整个序列保存到ArrayList
正如我前面提到的,时间复杂度仍然是
O(n^2)
但它肯定会减少查找序列的步骤数。由于您没有搜索所依据的先验信息,因此您必须至少访问网格中的每个单元格一次,即使您希望建立某种索引以优化搜索和查找。此外,如果您的网格将如此之小,则re不是寻找优化的理由,因为它们不会产生太大的影响。@EvilTak我不确定我必须访问每个单元格一次。C的大小总是5长,S的大小总是3长。所以我知道当它们的相对数组列表的大小正确时,我可以停止。而且,我知道优化这样的东西真的没有意义。但我的问题是如何减少查找所有位置所需的总步骤。当然这不会真的有什么区别,但这不是重点。威尔“C”和“s”总是成行吗?@harman786不,它们也可以是列如果你知道最短序列的长度为3,那么你只能在第3步检查对角线(第一步(2,0)-(0,2)。然后(5,0)-(0,5)等等)您能否对inbouds
函数进行更详细的扩展。是否打算检查下面对i
和/或j
执行的计算是否超出网格的范围?一个实现可能会有所帮助。此外,一些位置可以垂直放置。我是否可以再添加4个递归调用以获得序列w关于你在底部评论中提到的垂直位置?是的,我已经编辑了答案。它包括inbounds
implementation。我添加了一些评论,可以更清楚地说明方向