检查2D Array / Matrix中的元素是否形成循环

时间:2015-07-15 18:16:15

标签: java

我有一个代表网格的2D数组/矩阵。当元素在特定位置添加到网格时,矩阵等效位置用1填充(所以没有任何东西,有0)。

我应该如何检查网格上的元素是否形成循环? (他们不能以对角线连接)。

0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 1 1 1 0 0 0 
0 0 0 0 1 0 1 0 0 0 
0 0 0 0 1 1 1 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 

这是一个例子,元素会移动。

感谢您的帮助

3 个答案:

答案 0 :(得分:1)

看看Flood Fill。您可以在维基百科页面上找到伪代码。 有关此算法的完整示例,请查看Rosetta Code上的java实现。

您的设计的一般想法是:

  1. 找到一个起点(即1中的一个)
  2. 查看该点周围的所有内容,看看是否还有其他1个
  3. 注意你开始的位置,将起始1翻转为0并继续前进到邻近的1(递归)。
  4. 如果附近没有更多,请查看您的起始位置是否在附近,看看您是否已经完整循环。

答案 1 :(得分:1)

作为jkeuhlen的洪水填充解决方案的替代方案,你可以通过矩阵使用类似的东西来寻找循环:

for(int r = 1; r < intArray.length-1; r++)
        for (int c = 1; c < intArray[0].length-1; c++)
            if (intArray[r][c] == 1)
                continue;
            else if (intArray[r-1][c-1] == 1 && intArray[r-1][c] == 1 && intArray[r-1][c+1] == 1 && intArray[r][c-1] == 1 &&
                    intArray[r][c+1] == 1 && intArray[r+1][c-1] == 1 && intArray[r+1][c] == 1 && intArray[r+1][c+1] == 1)
                System.out.println("("+r+", "+c+")");

可能更适合这种情况。

答案 2 :(得分:1)

因为今天是比萨饼日,我会在评论中提供一些关于回溯的信息。

回溯的想法基本上是假设每个选项都有效,直到相反的证明。

在最坏的情况下,你正在检查每条路径(不是每个字段!),只是为了弄清楚,没有循环。

你开始“1”并不重要。

因此,基本算法可以这样写(伪代码):

private boolean testSolution(Position p, Position prior, List<Position> visited){
   //return true, if our current Position solves the problem
   if (visited.contains(p)){
     return true;
   }

   //this is now visited
   visited.add(p);

   //Else: Check, which options we have at the current position
   //and check if one of the neighbors is a valid solution.
   for (Position nextP : getNeighborsOf(p)){
      if (prior == null || !nextP.equals(prior)){
         if (testSolution(nextP, p, visited)){
            //this satisfies the condition!
            //we hit a position we visited a while ago but not exactly in 
            //the prior step. -> theres at least one loop.
            return true;
         }else{
            //check next neighbor for the current position
            // (no code required)
         }
      }else{
        //moving back would end in an infinite loop. avoid that.
        // (no code required)
      }
   }

   //no neighbor working? return false to return to the "prior"
   //position, so it can evaluate other options.
   return false;
}

这样调用:

if (testSolution(firstOneInTheGrid, null, new LinkedList<Position>())){
  //theres a loop
}else{
  //no loop found.
}
编辑:因为Pizza很好吃,我想检查一下我的解释是否正常 - 它可以工作(必须添加grid参数一次运行多个测试,如果只有一个网格,访问可能是静态/实例绑定)

public class Main {


    private static int[][] t1 = {
            {0,1,1,0},
            {0,1,1,0},
            {0,0,0,0},
            {0,0,0,0}
         };

    private static int[][] t2 = {
            {0,0,0,0},
            {0,1,1,1},
            {0,1,0,1},
            {0,1,1,1}
         };

    private static int[][] t3 = {
            {1,1,1,1},
            {1,0,0,1},
            {1,0,0,1},
            {1,1,1,1}
         };

    private static int[][] t4 = {
            {1,1,0,1},
            {0,1,0,1},
            {0,1,0,1},
            {1,1,1,1}
         };

    protected static class Position{
        public int x;
        public int y;

        public Position(int x, int y){
            this.x=x;
            this.y=y;
        }

        @Override
        public String toString() {
            return "Position [x=" + x + ", y=" + y + "]";
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + x;
            result = prime * result + y;
            return result;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Position other = (Position) obj;
            if (x != other.x)
                return false;
            if (y != other.y)
                return false;
            return true;
        }
    }

    public static void main(String[] argv) {
        test("t1", t1, new Position(1,0)); //static start position
        test("t2", t2, new Position(1,1)); //static start position
        test("t3", t3, new Position(0,0)); //static start position
        test("t4", t4, new Position(0,0)); //static start position
    }

    public static void test(String name, int[][] arr, Position start){
        System.out.println("Testing case " + name);
        if (testSolution(start, null, new LinkedList<Position>(), arr)){
            System.out.println("Loop Found!");
        }else{
            System.out.println("No Loop.");
        }
    }

    public static boolean testSolution(Position p,Position prior, List<Position> visited, int[][] grid){
        System.out.println("Current: " +p);

        if (visited.contains(p))
            return true;

        visited.add(p);

        for (Position nextP : getNeighbors(p, grid)) {
            if (prior == null || !nextP.equals(prior)){
                if (testSolution(nextP, p, visited, grid)){
                    return true;
                }
            }
        }

        return false;
    }

    public static List<Position> getNeighbors(Position p, int[][] grid){
        //Upper bound 3 hardcoded, could be dynamic.
        List<Position> result = new LinkedList<Position>();
          if (p.x > 0){ //left position
              Position np =new Position(p.x-1,p.y);
              if (grid[np.y][np.x]== 1)
                  result.add(np);
          }
          if (p.x < 3){ //right position
              Position np =new Position(p.x+1,p.y);
              if (grid[np.y][np.x]== 1)
                  result.add(np);
          }
          if (p.y > 0){ //top position
              Position np =new Position(p.x,p.y-1);
              if (grid[np.y][np.x]== 1)
                  result.add(np);
          }
          if (p.y < 3){ //bottom position
              Position np =new Position(p.x,p.y+1);
              if (grid[np.y][np.x]== 1)
                  result.add(np);
          }
        return result;

    }
}

结果:

Testing case t1
Current: Position [x=1, y=0]
Current: Position [x=2, y=0]
Current: Position [x=2, y=1]
Current: Position [x=1, y=1]
Current: Position [x=1, y=0]
Loop Found!
Testing case t2
Current: Position [x=1, y=1]
Current: Position [x=2, y=1]
Current: Position [x=3, y=1]
Current: Position [x=3, y=2]
Current: Position [x=3, y=3]
Current: Position [x=2, y=3]
Current: Position [x=1, y=3]
Current: Position [x=1, y=2]
Current: Position [x=1, y=1]
Loop Found!
Testing case t3
Current: Position [x=0, y=0]
Current: Position [x=1, y=0]
Current: Position [x=2, y=0]
Current: Position [x=3, y=0]
Current: Position [x=3, y=1]
Current: Position [x=3, y=2]
Current: Position [x=3, y=3]
Current: Position [x=2, y=3]
Current: Position [x=1, y=3]
Current: Position [x=0, y=3]
Current: Position [x=0, y=2]
Current: Position [x=0, y=1]
Current: Position [x=0, y=0]
Loop Found!
Testing case t4
Current: Position [x=0, y=0]
Current: Position [x=1, y=0]
Current: Position [x=1, y=1]
Current: Position [x=1, y=2]
Current: Position [x=1, y=3]
Current: Position [x=0, y=3]
Current: Position [x=2, y=3]
Current: Position [x=3, y=3]
Current: Position [x=3, y=2]
Current: Position [x=3, y=1]
Current: Position [x=3, y=0]
No Loop.

该死的,现在我提供了一个解决我的评论的方法。

针对暴力的优势:未选中“0”字段。因此,如果您正在搜索2x2循环时间复杂度保持不变,无论是2x2矩阵还是500Mx500M(搜索任何 1除外)

注意:这假设所有“1”都已连接,所以不是这样的:

1 0 0 0 
0 0 1 1
0 0 1 1 
0 0 0 0 

但您也可以通过检查是否所有“1”字段至少评估过一次来覆盖这一点。 - 否则开始对尚未评​​估的“1”进行另一次搜索。