【问题标题】:Finding a loop within a Grid (Java)在网格中查找循环 (Java)
【发布时间】:2021-11-26 21:50:22
【问题描述】:

我目前正在处理一个问题,其中我有一个包含 n 行和 m 列的 2D 字符列表。列表中的所述字符是代表 4 个坐标的“N”、“S”、“E”或“W”。

例如,一个 4 行 5 列的二维列表可以表示为List<List<Character>> grid =

SESWE
EESNW
NWEEN
EWSEN

在这个问题中,我在网格中也有一个起始位置(总是在边缘的某个地方)。例如,在这个问题中,我的起始位置是 (0,0)。

我必须解决的问题是,我必须按照指示穿过网格并确定循环发生的位置、循环之前有多少指令以及循环有多少指令。要按照网格中的方向进行操作,您只需按照网格中的任何坐标进行操作即可。例如,(0,0) 是 S 或 South,因此您向下一个元素到 (1, 0),即 E 或 East。从那里你向东一个坐标到 (1,1),这是另一个 E 或东。以此类推。

对于这个特定的网格,如果您沿着 (0,0) 的坐标,通过网格的路径应该如下所示:

在这个网格中,循环本身有8条指令,循环之前有3条指令。

我很难想出一个可以实现这一目标的算法。起初我想我应该首先沿着网格的路径走,并在我访问过的每个元素上留下一点面包屑,这样如果我再次访问它,我就知道我在循环中。因此,在这种情况下,在我访问了所有元素后,它会如下所示:


. E . . E
. . . . .
N W . . .
E W S E N

我通过以下方式完成了这项工作:

while (gridCopy.get(curRow).get(curCol) != '.') {
            if (gridCopy.get(curRow).get(curCol) != '.') {
                if (gridCopy.get(curRow).get(curCol) == 'N') {
                    gridCopy.get(curRow).set(curCol, '.');
                    curRow--;
                } else if (gridCopy.get(curRow).get(curCol) == 'S') {
                    gridCopy.get(curRow).set(curCol, '.');
                    curRow++;
                } else if (gridCopy.get(curRow).get(curCol) == 'W') {
                    gridCopy.get(curRow).set(curCol, '.');
                    curCol--;
                } else if (gridCopy.get(curRow).get(curCol) == 'E') {
                    gridCopy.get(curRow).set(curCol, '.');
                    curCol++;
                }
            }
        }

不过,所有这些只是告诉我,我确实在网格中有一个循环,而没有告诉我循环有多少条指令以及循环之前有多少条指令。

谁能帮我指出正确的方向?

【问题讨论】:

    标签: java arraylist multidimensional-array grid coordinates


    【解决方案1】:

    这是一种可能的实现方式。基本上,您将遍历的坐标存储在一个列表中,如果坐标已经在该列表中,那么您已经找到了一个循环。我没有添加代码来检查搜索是否超出范围,所以我假设所有网格都表现良好并且它们都至少有一个循环。无论如何下面是带有更多解释的代码作为cmets:

    // Class to store the coordinates
    public static class Coordinate {
        private int x;
        private int y;
    
        public Coordinate(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
        public int getX() {
            return x;
        }
    
        public int getY() {
            return y;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            Coordinate that = (Coordinate) o;
    
            if (x != that.x) return false;
            return y == that.y;
        }
    }
    

    循环查找器:

    public static void loopFinder(List<List<Character>> grid, int startingX, int startingY) {
        // Not checking if one went outside of the grid
    
        // Store the coordinates we've traversed, if we find a duplicate then there's a loop
        List<Coordinate> traversedCoordinates = new ArrayList<>();
        Coordinate currentCoordinate = new Coordinate(startingX, startingY);
        traversedCoordinates.add(currentCoordinate);
    
        while (true) {
            char direction = grid.get(currentCoordinate.getY()).get(currentCoordinate.getX());
            switch (direction){
                case 'N':
                    currentCoordinate = new Coordinate(currentCoordinate.getX(), currentCoordinate.getY() - 1);
                    break;
                case 'E':
                    currentCoordinate = new Coordinate(currentCoordinate.getX() + 1, currentCoordinate.getY());
                    break;
                case 'S':
                    currentCoordinate = new Coordinate(currentCoordinate.getX(), currentCoordinate.getY() + 1);
                    break;
                case 'W':
                    currentCoordinate = new Coordinate(currentCoordinate.getX() - 1, currentCoordinate.getY());
                    break;
            }
            if(traversedCoordinates.contains(currentCoordinate)) {
                // found a loop
                traversedCoordinates.add(currentCoordinate);
                break;
            }
            traversedCoordinates.add(currentCoordinate);
        }
    
        // find index of current coordinate that will give us how many instructions before the loop started
        int numOfInstructionsBefore = traversedCoordinates.indexOf(currentCoordinate);
        int lengthOfLoop = traversedCoordinates.size() - numOfInstructionsBefore - 1;
    
        // I don't know if you need to include the starting and ending point of the loop
        // in that case you might have to offset the two values above.
        System.out.println("Number of instruction before the loop: " + numOfInstructionsBefore);
        System.out.println("Length of the loop: " + lengthOfLoop);
    }
    

    用法:

    public static void  main(String[] args) {
    
        List<List<Character>> grid = new ArrayList<>();
        grid.add(List.of('S', 'E', 'S', 'W', 'E'));
        grid.add(List.of('E', 'E', 'S', 'N', 'W'));
        grid.add(List.of('N', 'W', 'E', 'E', 'N'));
        grid.add(List.of('E', 'W', 'S', 'E', 'N'));
    
        loopFinder(grid, 0, 0);
    }
    

    输出:

    Number of instruction before the loop: 3
    Length of the loop: 8
    

    【讨论】:

    • 完美。非常感谢
    • @ParkerHarrelson123 很高兴我能提供帮助。我在重新阅读问题后进行了更新,并意识到循环的起点不必计算两次,因此我添加了-1 以使循环中的指令总数为 8 而不是 9。
    猜你喜欢
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-18
    相关资源
    最近更新 更多