Java 高效搜索多个项目的二维矩阵

Java 高效搜索多个项目的二维矩阵,java,algorithm,search,Java,Algorithm,Search,我有一个25x25的网格,看起来像这样。在整个网格中有两个随机的字符串序列,我正在尝试开发一些有效的方法来搜索网格并找到每个位置的点 我看了两个在2D数组中搜索的算法示例,大多数算法都集中在查找单个字符或数字上 在这个特定的实例中,我有什么样的搜索选项?我在一次搜索中实现了一个基本步骤,如下所示: public void search(String[][] grid) { int cellsSearched = 0; List<Point> cLocations =

我有一个25x25的网格,看起来像这样。在整个网格中有两个随机的字符串序列,我正在尝试开发一些有效的方法来搜索网格并找到每个位置的点

我看了两个在2D数组中搜索的算法示例,大多数算法都集中在查找单个字符或数字上

在这个特定的实例中,我有什么样的搜索选项?我在一次搜索中实现了一个基本步骤,如下所示:

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。我添加了一些评论,可以更清楚地说明方向