有效地搜索多个项目的2D矩阵

时间:2018-04-16 04:18:23

标签: java algorithm search

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

enter image description here

我已经查看了几个搜索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++;
        }
    }
}

但这显然不是最有效的搜索方式。

我曾想过将网格划分为象限并一次搜索一个象限,但这似乎仍然存在太多潜在的缺陷。 (例如,两个序列都位于搜索的最后一个象限中。)

我的问题是,如何以尽可能少的步骤搜索此网格并收集其序列中每个字符的坐标?

1 个答案:

答案 0 :(得分:1)

您可以使用一个技巧来改善搜索的运行时间。
但由于它是一个网格,并且由于我们没有关于'S''C'的展示位置的信息,因此时间复杂度将保持O(n^2)。 除此之外,

一旦你点击'S''C',你实际上可以从那里存储它们的整个序列。您基本上必须检查当前字符两侧是否有相同的字符并继续。
你可以有一个额外的2D boolean数组来跟踪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 
        */
    }
}

您看到,只要您点击'S''C'getSeries功能就会自动将整个序列保存到ArrayList

正如我前面提到的,时间复杂度仍为O(n^2),但肯定会减少查找序列的步骤数。